| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715771677177718771977207721772277237724772577267727772877297730773177327733773477357736773777387739774077417742774377447745774677477748774977507751775277537754775577567757775877597760776177627763776477657766776777687769777077717772777377747775777677777778777977807781778277837784778577867787778877897790779177927793779477957796779777987799780078017802780378047805780678077808780978107811781278137814781578167817781878197820782178227823782478257826782778287829783078317832783378347835783678377838783978407841784278437844784578467847784878497850785178527853785478557856785778587859786078617862786378647865786678677868786978707871787278737874787578767877787878797880788178827883788478857886788778887889789078917892789378947895789678977898789979007901790279037904790579067907790879097910791179127913791479157916791779187919792079217922792379247925792679277928792979307931793279337934793579367937793879397940794179427943794479457946794779487949795079517952795379547955795679577958795979607961796279637964796579667967796879697970797179727973797479757976797779787979798079817982798379847985798679877988798979907991799279937994799579967997799879998000800180028003800480058006800780088009801080118012801380148015801680178018801980208021802280238024802580268027802880298030803180328033803480358036803780388039804080418042804380448045804680478048804980508051805280538054805580568057805880598060806180628063806480658066806780688069807080718072807380748075807680778078807980808081808280838084808580868087808880898090809180928093809480958096809780988099810081018102810381048105810681078108810981108111811281138114811581168117811881198120812181228123812481258126812781288129813081318132813381348135813681378138813981408141814281438144814581468147814881498150815181528153815481558156815781588159816081618162816381648165816681678168816981708171817281738174817581768177817881798180818181828183818481858186818781888189819081918192819381948195819681978198819982008201820282038204820582068207820882098210821182128213821482158216821782188219822082218222822382248225822682278228822982308231823282338234823582368237823882398240824182428243824482458246824782488249825082518252825382548255825682578258825982608261826282638264826582668267826882698270827182728273827482758276827782788279828082818282828382848285828682878288828982908291829282938294829582968297829882998300830183028303830483058306830783088309831083118312831383148315831683178318831983208321832283238324832583268327832883298330833183328333833483358336833783388339834083418342834383448345834683478348834983508351835283538354835583568357835883598360836183628363836483658366836783688369837083718372837383748375837683778378837983808381838283838384838583868387838883898390839183928393839483958396839783988399840084018402840384048405840684078408840984108411841284138414841584168417841884198420842184228423842484258426842784288429843084318432843384348435843684378438843984408441844284438444844584468447844884498450845184528453845484558456845784588459846084618462846384648465846684678468846984708471847284738474847584768477847884798480848184828483848484858486848784888489849084918492849384948495849684978498849985008501850285038504850585068507850885098510851185128513851485158516851785188519852085218522852385248525852685278528852985308531853285338534853585368537853885398540854185428543854485458546854785488549855085518552855385548555855685578558855985608561856285638564856585668567856885698570857185728573857485758576857785788579858085818582858385848585858685878588858985908591859285938594859585968597859885998600860186028603860486058606860786088609861086118612861386148615861686178618861986208621862286238624862586268627862886298630863186328633863486358636863786388639864086418642864386448645864686478648864986508651865286538654865586568657865886598660866186628663866486658666866786688669867086718672867386748675867686778678867986808681868286838684868586868687868886898690869186928693869486958696869786988699870087018702870387048705870687078708870987108711871287138714871587168717871887198720872187228723872487258726872787288729873087318732873387348735873687378738873987408741874287438744874587468747874887498750875187528753875487558756875787588759876087618762876387648765876687678768876987708771877287738774877587768777877887798780878187828783878487858786878787888789879087918792879387948795879687978798879988008801880288038804880588068807880888098810881188128813881488158816881788188819882088218822882388248825882688278828882988308831883288338834883588368837883888398840884188428843884488458846884788488849885088518852885388548855885688578858885988608861886288638864886588668867886888698870887188728873887488758876887788788879888088818882888388848885888688878888888988908891889288938894889588968897889888998900890189028903890489058906890789088909891089118912891389148915891689178918891989208921892289238924892589268927892889298930893189328933893489358936893789388939894089418942894389448945894689478948894989508951895289538954895589568957895889598960896189628963896489658966896789688969897089718972897389748975897689778978897989808981898289838984898589868987898889898990899189928993899489958996899789988999900090019002900390049005900690079008900990109011901290139014901590169017901890199020902190229023902490259026902790289029903090319032903390349035903690379038903990409041904290439044904590469047904890499050905190529053905490559056905790589059906090619062906390649065906690679068906990709071907290739074907590769077907890799080908190829083908490859086908790889089909090919092909390949095909690979098909991009101910291039104910591069107910891099110911191129113911491159116911791189119912091219122912391249125912691279128912991309131913291339134913591369137913891399140914191429143914491459146914791489149915091519152915391549155915691579158915991609161916291639164916591669167916891699170917191729173917491759176917791789179918091819182918391849185918691879188918991909191919291939194919591969197919891999200920192029203920492059206920792089209921092119212921392149215921692179218921992209221922292239224922592269227922892299230923192329233923492359236923792389239924092419242924392449245924692479248924992509251925292539254925592569257925892599260926192629263926492659266926792689269927092719272927392749275927692779278927992809281928292839284928592869287928892899290929192929293929492959296929792989299930093019302930393049305930693079308930993109311931293139314931593169317931893199320932193229323932493259326932793289329933093319332933393349335933693379338933993409341934293439344934593469347934893499350935193529353935493559356935793589359936093619362936393649365936693679368936993709371937293739374937593769377937893799380938193829383938493859386938793889389939093919392939393949395939693979398939994009401940294039404940594069407940894099410941194129413941494159416941794189419942094219422942394249425942694279428942994309431943294339434943594369437943894399440944194429443944494459446944794489449945094519452945394549455945694579458945994609461946294639464946594669467946894699470947194729473947494759476947794789479948094819482948394849485948694879488948994909491949294939494949594969497949894999500950195029503950495059506950795089509951095119512951395149515951695179518951995209521952295239524952595269527952895299530953195329533953495359536953795389539954095419542954395449545954695479548954995509551955295539554955595569557955895599560956195629563956495659566956795689569957095719572957395749575957695779578957995809581958295839584958595869587958895899590959195929593959495959596959795989599960096019602960396049605960696079608960996109611961296139614961596169617961896199620962196229623962496259626962796289629963096319632963396349635963696379638963996409641964296439644964596469647964896499650965196529653965496559656965796589659966096619662966396649665966696679668966996709671967296739674967596769677967896799680968196829683968496859686968796889689969096919692969396949695969696979698969997009701970297039704970597069707970897099710971197129713971497159716971797189719972097219722972397249725972697279728972997309731973297339734973597369737973897399740974197429743974497459746974797489749975097519752975397549755975697579758975997609761976297639764976597669767976897699770977197729773977497759776977797789779978097819782978397849785978697879788978997909791979297939794979597969797979897999800980198029803980498059806980798089809981098119812981398149815981698179818981998209821982298239824982598269827982898299830983198329833983498359836983798389839984098419842984398449845984698479848984998509851985298539854985598569857985898599860986198629863986498659866986798689869987098719872987398749875987698779878987998809881988298839884988598869887988898899890989198929893989498959896989798989899990099019902990399049905990699079908990999109911991299139914991599169917991899199920992199229923992499259926992799289929993099319932993399349935993699379938993999409941994299439944994599469947994899499950995199529953995499559956995799589959996099619962996399649965996699679968996999709971997299739974997599769977997899799980998199829983998499859986998799889989999099919992999399949995999699979998999910000100011000210003100041000510006100071000810009100101001110012100131001410015100161001710018100191002010021100221002310024100251002610027100281002910030100311003210033100341003510036100371003810039100401004110042100431004410045100461004710048100491005010051100521005310054100551005610057100581005910060100611006210063100641006510066100671006810069100701007110072100731007410075100761007710078100791008010081100821008310084100851008610087100881008910090100911009210093100941009510096100971009810099101001010110102101031010410105101061010710108101091011010111101121011310114101151011610117101181011910120101211012210123101241012510126101271012810129101301013110132101331013410135101361013710138101391014010141101421014310144101451014610147101481014910150101511015210153101541015510156101571015810159101601016110162101631016410165101661016710168101691017010171101721017310174101751017610177101781017910180101811018210183101841018510186101871018810189101901019110192101931019410195101961019710198101991020010201102021020310204102051020610207102081020910210102111021210213102141021510216102171021810219102201022110222102231022410225102261022710228102291023010231102321023310234102351023610237102381023910240102411024210243102441024510246102471024810249102501025110252102531025410255102561025710258102591026010261102621026310264102651026610267102681026910270102711027210273102741027510276102771027810279102801028110282102831028410285102861028710288102891029010291102921029310294102951029610297102981029910300103011030210303103041030510306103071030810309103101031110312103131031410315103161031710318103191032010321103221032310324103251032610327103281032910330103311033210333103341033510336103371033810339103401034110342103431034410345103461034710348103491035010351103521035310354103551035610357103581035910360103611036210363103641036510366103671036810369103701037110372103731037410375103761037710378103791038010381103821038310384103851038610387103881038910390103911039210393103941039510396103971039810399104001040110402104031040410405104061040710408104091041010411104121041310414104151041610417104181041910420104211042210423104241042510426104271042810429104301043110432104331043410435104361043710438104391044010441104421044310444104451044610447104481044910450104511045210453104541045510456104571045810459104601046110462104631046410465104661046710468104691047010471104721047310474104751047610477104781047910480104811048210483104841048510486104871048810489104901049110492104931049410495104961049710498104991050010501105021050310504105051050610507105081050910510105111051210513105141051510516105171051810519105201052110522105231052410525105261052710528105291053010531105321053310534105351053610537105381053910540105411054210543105441054510546105471054810549105501055110552105531055410555105561055710558105591056010561105621056310564105651056610567105681056910570105711057210573105741057510576105771057810579105801058110582105831058410585105861058710588105891059010591105921059310594105951059610597105981059910600106011060210603106041060510606106071060810609106101061110612106131061410615106161061710618106191062010621106221062310624106251062610627106281062910630106311063210633106341063510636106371063810639106401064110642106431064410645106461064710648106491065010651106521065310654106551065610657106581065910660106611066210663106641066510666106671066810669106701067110672106731067410675106761067710678106791068010681106821068310684106851068610687106881068910690106911069210693106941069510696106971069810699107001070110702107031070410705107061070710708107091071010711107121071310714107151071610717107181071910720107211072210723107241072510726107271072810729107301073110732107331073410735107361073710738107391074010741107421074310744107451074610747107481074910750107511075210753107541075510756107571075810759107601076110762107631076410765107661076710768107691077010771107721077310774107751077610777107781077910780107811078210783107841078510786107871078810789107901079110792107931079410795107961079710798107991080010801108021080310804108051080610807108081080910810108111081210813108141081510816108171081810819108201082110822108231082410825108261082710828108291083010831108321083310834108351083610837108381083910840108411084210843108441084510846108471084810849108501085110852108531085410855108561085710858108591086010861108621086310864108651086610867108681086910870108711087210873108741087510876108771087810879108801088110882108831088410885108861088710888108891089010891108921089310894108951089610897108981089910900109011090210903109041090510906109071090810909109101091110912109131091410915109161091710918109191092010921109221092310924109251092610927109281092910930109311093210933109341093510936109371093810939109401094110942109431094410945109461094710948109491095010951109521095310954109551095610957109581095910960109611096210963109641096510966109671096810969109701097110972109731097410975109761097710978109791098010981109821098310984109851098610987109881098910990109911099210993109941099510996109971099810999110001100111002110031100411005110061100711008110091101011011110121101311014110151101611017110181101911020110211102211023110241102511026110271102811029110301103111032110331103411035110361103711038110391104011041110421104311044110451104611047110481104911050110511105211053110541105511056110571105811059110601106111062110631106411065110661106711068110691107011071110721107311074110751107611077110781107911080110811108211083110841108511086110871108811089110901109111092110931109411095110961109711098110991110011101111021110311104111051110611107111081110911110111111111211113111141111511116111171111811119111201112111122111231112411125111261112711128111291113011131111321113311134111351113611137111381113911140111411114211143111441114511146111471114811149111501115111152111531115411155111561115711158111591116011161111621116311164111651116611167111681116911170111711117211173111741117511176111771117811179111801118111182111831118411185111861118711188111891119011191111921119311194111951119611197111981119911200112011120211203112041120511206112071120811209112101121111212112131121411215112161121711218112191122011221112221122311224112251122611227112281122911230112311123211233112341123511236112371123811239112401124111242112431124411245112461124711248112491125011251112521125311254112551125611257112581125911260112611126211263112641126511266112671126811269112701127111272112731127411275112761127711278112791128011281112821128311284112851128611287112881128911290112911129211293112941129511296112971129811299113001130111302113031130411305113061130711308113091131011311113121131311314113151131611317113181131911320113211132211323113241132511326113271132811329113301133111332113331133411335113361133711338113391134011341113421134311344113451134611347113481134911350113511135211353113541135511356113571135811359113601136111362113631136411365113661136711368113691137011371113721137311374113751137611377113781137911380113811138211383113841138511386113871138811389113901139111392113931139411395113961139711398113991140011401114021140311404114051140611407114081140911410114111141211413114141141511416114171141811419114201142111422114231142411425114261142711428114291143011431114321143311434114351143611437114381143911440114411144211443114441144511446114471144811449114501145111452114531145411455114561145711458114591146011461114621146311464114651146611467114681146911470114711147211473114741147511476114771147811479114801148111482114831148411485114861148711488114891149011491114921149311494114951149611497114981149911500115011150211503115041150511506115071150811509115101151111512115131151411515115161151711518115191152011521115221152311524115251152611527115281152911530115311153211533115341153511536115371153811539115401154111542115431154411545115461154711548115491155011551115521155311554115551155611557115581155911560115611156211563115641156511566115671156811569115701157111572115731157411575115761157711578115791158011581115821158311584115851158611587115881158911590115911159211593115941159511596115971159811599116001160111602116031160411605116061160711608116091161011611116121161311614116151161611617116181161911620116211162211623116241162511626116271162811629116301163111632116331163411635116361163711638116391164011641116421164311644116451164611647116481164911650116511165211653116541165511656116571165811659116601166111662116631166411665116661166711668116691167011671116721167311674116751167611677116781167911680116811168211683116841168511686116871168811689116901169111692116931169411695116961169711698116991170011701117021170311704117051170611707117081170911710117111171211713117141171511716117171171811719117201172111722117231172411725117261172711728117291173011731117321173311734117351173611737117381173911740117411174211743117441174511746117471174811749117501175111752117531175411755117561175711758117591176011761117621176311764117651176611767117681176911770117711177211773117741177511776117771177811779117801178111782117831178411785117861178711788117891179011791117921179311794117951179611797117981179911800118011180211803118041180511806118071180811809118101181111812118131181411815118161181711818118191182011821118221182311824118251182611827118281182911830118311183211833118341183511836118371183811839118401184111842118431184411845118461184711848118491185011851118521185311854118551185611857118581185911860118611186211863118641186511866118671186811869118701187111872118731187411875118761187711878118791188011881118821188311884118851188611887118881188911890118911189211893118941189511896118971189811899119001190111902119031190411905119061190711908119091191011911119121191311914119151191611917119181191911920119211192211923119241192511926119271192811929119301193111932119331193411935119361193711938119391194011941119421194311944119451194611947119481194911950119511195211953119541195511956119571195811959119601196111962119631196411965119661196711968119691197011971119721197311974119751197611977119781197911980119811198211983119841198511986119871198811989119901199111992119931199411995119961199711998119991200012001120021200312004120051200612007120081200912010120111201212013120141201512016120171201812019120201202112022120231202412025120261202712028120291203012031120321203312034120351203612037120381203912040120411204212043120441204512046120471204812049120501205112052120531205412055120561205712058120591206012061120621206312064120651206612067120681206912070120711207212073120741207512076120771207812079120801208112082120831208412085120861208712088120891209012091120921209312094120951209612097120981209912100121011210212103121041210512106121071210812109121101211112112121131211412115121161211712118121191212012121121221212312124121251212612127121281212912130121311213212133121341213512136121371213812139121401214112142121431214412145121461214712148121491215012151121521215312154121551215612157121581215912160121611216212163121641216512166121671216812169121701217112172121731217412175121761217712178121791218012181121821218312184121851218612187121881218912190121911219212193121941219512196121971219812199122001220112202122031220412205122061220712208122091221012211122121221312214122151221612217122181221912220122211222212223122241222512226122271222812229122301223112232122331223412235122361223712238122391224012241122421224312244122451224612247122481224912250122511225212253122541225512256122571225812259122601226112262122631226412265122661226712268122691227012271122721227312274122751227612277122781227912280122811228212283122841228512286122871228812289122901229112292122931229412295122961229712298122991230012301123021230312304123051230612307123081230912310123111231212313123141231512316123171231812319123201232112322123231232412325123261232712328123291233012331123321233312334123351233612337123381233912340123411234212343123441234512346123471234812349123501235112352123531235412355123561235712358123591236012361123621236312364123651236612367123681236912370123711237212373123741237512376123771237812379123801238112382123831238412385123861238712388123891239012391123921239312394123951239612397123981239912400124011240212403124041240512406124071240812409124101241112412124131241412415124161241712418124191242012421124221242312424124251242612427124281242912430124311243212433124341243512436124371243812439124401244112442124431244412445124461244712448124491245012451124521245312454124551245612457124581245912460124611246212463124641246512466124671246812469124701247112472124731247412475124761247712478124791248012481124821248312484124851248612487124881248912490124911249212493124941249512496124971249812499125001250112502125031250412505125061250712508125091251012511125121251312514125151251612517125181251912520125211252212523125241252512526125271252812529125301253112532125331253412535125361253712538125391254012541125421254312544125451254612547125481254912550125511255212553125541255512556125571255812559125601256112562125631256412565125661256712568125691257012571125721257312574125751257612577125781257912580125811258212583125841258512586125871258812589125901259112592125931259412595125961259712598125991260012601126021260312604126051260612607126081260912610126111261212613126141261512616126171261812619126201262112622126231262412625126261262712628126291263012631126321263312634126351263612637126381263912640126411264212643126441264512646126471264812649126501265112652126531265412655126561265712658126591266012661126621266312664126651266612667126681266912670126711267212673126741267512676126771267812679126801268112682126831268412685126861268712688126891269012691126921269312694126951269612697126981269912700127011270212703127041270512706127071270812709127101271112712127131271412715127161271712718127191272012721127221272312724127251272612727127281272912730127311273212733127341273512736127371273812739127401274112742127431274412745127461274712748127491275012751127521275312754127551275612757127581275912760127611276212763127641276512766127671276812769127701277112772127731277412775127761277712778127791278012781127821278312784127851278612787127881278912790127911279212793127941279512796127971279812799128001280112802128031280412805128061280712808128091281012811128121281312814128151281612817128181281912820128211282212823128241282512826128271282812829128301283112832128331283412835128361283712838128391284012841128421284312844128451284612847128481284912850128511285212853128541285512856128571285812859128601286112862128631286412865128661286712868128691287012871128721287312874128751287612877128781287912880128811288212883128841288512886128871288812889128901289112892128931289412895128961289712898128991290012901129021290312904129051290612907129081290912910129111291212913129141291512916129171291812919129201292112922129231292412925129261292712928129291293012931129321293312934129351293612937129381293912940129411294212943129441294512946129471294812949129501295112952129531295412955129561295712958129591296012961129621296312964129651296612967129681296912970129711297212973129741297512976129771297812979129801298112982129831298412985129861298712988129891299012991129921299312994129951299612997129981299913000130011300213003130041300513006130071300813009130101301113012130131301413015130161301713018130191302013021130221302313024130251302613027130281302913030130311303213033130341303513036130371303813039130401304113042130431304413045130461304713048130491305013051130521305313054130551305613057130581305913060130611306213063130641306513066130671306813069130701307113072130731307413075130761307713078130791308013081130821308313084130851308613087130881308913090130911309213093130941309513096130971309813099131001310113102131031310413105131061310713108131091311013111131121311313114131151311613117131181311913120131211312213123131241312513126131271312813129131301313113132131331313413135131361313713138131391314013141131421314313144131451314613147131481314913150131511315213153131541315513156131571315813159131601316113162131631316413165131661316713168131691317013171131721317313174131751317613177131781317913180131811318213183131841318513186131871318813189131901319113192131931319413195131961319713198131991320013201132021320313204132051320613207132081320913210132111321213213132141321513216132171321813219132201322113222132231322413225132261322713228132291323013231132321323313234132351323613237132381323913240132411324213243132441324513246132471324813249132501325113252132531325413255132561325713258132591326013261132621326313264132651326613267132681326913270132711327213273132741327513276132771327813279132801328113282132831328413285132861328713288132891329013291132921329313294132951329613297132981329913300133011330213303133041330513306133071330813309133101331113312133131331413315133161331713318133191332013321133221332313324133251332613327133281332913330133311333213333133341333513336133371333813339133401334113342133431334413345133461334713348133491335013351133521335313354133551335613357133581335913360133611336213363133641336513366133671336813369133701337113372133731337413375133761337713378133791338013381133821338313384133851338613387133881338913390133911339213393133941339513396133971339813399134001340113402134031340413405134061340713408134091341013411134121341313414134151341613417134181341913420134211342213423134241342513426134271342813429134301343113432134331343413435134361343713438134391344013441134421344313444134451344613447134481344913450134511345213453134541345513456134571345813459134601346113462134631346413465134661346713468134691347013471134721347313474134751347613477134781347913480134811348213483134841348513486134871348813489134901349113492134931349413495134961349713498134991350013501135021350313504135051350613507135081350913510135111351213513135141351513516135171351813519135201352113522135231352413525135261352713528135291353013531135321353313534135351353613537135381353913540135411354213543135441354513546135471354813549135501355113552135531355413555135561355713558135591356013561135621356313564135651356613567135681356913570135711357213573135741357513576135771357813579135801358113582135831358413585135861358713588135891359013591135921359313594135951359613597135981359913600136011360213603136041360513606136071360813609136101361113612136131361413615136161361713618136191362013621136221362313624136251362613627136281362913630136311363213633136341363513636136371363813639136401364113642136431364413645136461364713648136491365013651136521365313654136551365613657136581365913660136611366213663136641366513666136671366813669136701367113672136731367413675136761367713678136791368013681136821368313684136851368613687136881368913690136911369213693136941369513696136971369813699137001370113702137031370413705137061370713708137091371013711137121371313714137151371613717137181371913720137211372213723137241372513726137271372813729137301373113732137331373413735137361373713738137391374013741137421374313744137451374613747137481374913750137511375213753137541375513756137571375813759137601376113762137631376413765137661376713768137691377013771137721377313774137751377613777137781377913780137811378213783137841378513786137871378813789137901379113792137931379413795137961379713798137991380013801138021380313804138051380613807138081380913810138111381213813138141381513816138171381813819138201382113822138231382413825138261382713828138291383013831138321383313834138351383613837138381383913840138411384213843138441384513846138471384813849138501385113852138531385413855138561385713858138591386013861138621386313864138651386613867138681386913870138711387213873138741387513876138771387813879138801388113882138831388413885138861388713888138891389013891138921389313894138951389613897138981389913900139011390213903139041390513906139071390813909139101391113912139131391413915139161391713918139191392013921139221392313924139251392613927139281392913930139311393213933139341393513936139371393813939139401394113942139431394413945139461394713948139491395013951139521395313954139551395613957139581395913960139611396213963139641396513966139671396813969139701397113972139731397413975139761397713978139791398013981139821398313984139851398613987139881398913990139911399213993139941399513996139971399813999140001400114002140031400414005140061400714008140091401014011140121401314014140151401614017140181401914020140211402214023140241402514026140271402814029140301403114032140331403414035140361403714038140391404014041140421404314044140451404614047140481404914050140511405214053140541405514056140571405814059140601406114062140631406414065140661406714068140691407014071140721407314074140751407614077140781407914080140811408214083140841408514086140871408814089140901409114092140931409414095140961409714098140991410014101141021410314104141051410614107141081410914110141111411214113141141411514116141171411814119141201412114122141231412414125141261412714128141291413014131141321413314134141351413614137141381413914140141411414214143141441414514146141471414814149141501415114152141531415414155141561415714158141591416014161141621416314164141651416614167141681416914170141711417214173141741417514176141771417814179141801418114182141831418414185141861418714188141891419014191141921419314194141951419614197141981419914200142011420214203142041420514206142071420814209142101421114212142131421414215142161421714218142191422014221142221422314224142251422614227142281422914230142311423214233142341423514236142371423814239142401424114242142431424414245142461424714248142491425014251142521425314254142551425614257142581425914260142611426214263142641426514266142671426814269142701427114272142731427414275142761427714278142791428014281142821428314284142851428614287142881428914290142911429214293142941429514296142971429814299143001430114302143031430414305143061430714308143091431014311143121431314314143151431614317143181431914320143211432214323143241432514326143271432814329143301433114332143331433414335143361433714338143391434014341143421434314344143451434614347143481434914350143511435214353143541435514356143571435814359143601436114362143631436414365143661436714368143691437014371143721437314374143751437614377143781437914380143811438214383143841438514386143871438814389143901439114392143931439414395143961439714398143991440014401144021440314404144051440614407144081440914410144111441214413144141441514416144171441814419144201442114422144231442414425144261442714428144291443014431144321443314434144351443614437144381443914440144411444214443144441444514446144471444814449144501445114452144531445414455144561445714458144591446014461144621446314464144651446614467144681446914470144711447214473144741447514476144771447814479144801448114482144831448414485144861448714488144891449014491144921449314494144951449614497144981449914500145011450214503145041450514506145071450814509145101451114512145131451414515145161451714518145191452014521145221452314524145251452614527145281452914530145311453214533145341453514536145371453814539145401454114542145431454414545145461454714548145491455014551145521455314554145551455614557145581455914560145611456214563145641456514566145671456814569145701457114572145731457414575145761457714578145791458014581145821458314584145851458614587145881458914590145911459214593145941459514596145971459814599146001460114602146031460414605146061460714608146091461014611146121461314614146151461614617146181461914620146211462214623146241462514626146271462814629146301463114632146331463414635146361463714638146391464014641146421464314644146451464614647146481464914650146511465214653146541465514656146571465814659146601466114662146631466414665146661466714668146691467014671146721467314674146751467614677146781467914680146811468214683146841468514686146871468814689146901469114692146931469414695146961469714698146991470014701147021470314704147051470614707147081470914710147111471214713147141471514716147171471814719147201472114722147231472414725147261472714728147291473014731147321473314734147351473614737147381473914740147411474214743147441474514746147471474814749147501475114752147531475414755147561475714758147591476014761147621476314764147651476614767147681476914770147711477214773147741477514776147771477814779147801478114782147831478414785147861478714788147891479014791147921479314794147951479614797147981479914800148011480214803148041480514806148071480814809148101481114812148131481414815148161481714818148191482014821148221482314824148251482614827148281482914830148311483214833148341483514836148371483814839148401484114842148431484414845148461484714848148491485014851148521485314854148551485614857148581485914860148611486214863148641486514866148671486814869148701487114872148731487414875148761487714878148791488014881148821488314884148851488614887148881488914890148911489214893148941489514896148971489814899149001490114902149031490414905149061490714908149091491014911149121491314914149151491614917149181491914920149211492214923149241492514926149271492814929149301493114932149331493414935149361493714938149391494014941149421494314944149451494614947149481494914950149511495214953149541495514956149571495814959149601496114962149631496414965149661496714968149691497014971149721497314974149751497614977149781497914980149811498214983149841498514986149871498814989149901499114992149931499414995149961499714998149991500015001150021500315004150051500615007150081500915010150111501215013150141501515016150171501815019150201502115022150231502415025150261502715028150291503015031150321503315034150351503615037150381503915040150411504215043150441504515046150471504815049150501505115052150531505415055150561505715058150591506015061150621506315064150651506615067150681506915070150711507215073150741507515076150771507815079150801508115082150831508415085150861508715088150891509015091150921509315094150951509615097150981509915100151011510215103151041510515106151071510815109151101511115112151131511415115151161511715118151191512015121151221512315124151251512615127151281512915130151311513215133151341513515136151371513815139151401514115142151431514415145151461514715148151491515015151151521515315154151551515615157151581515915160151611516215163151641516515166151671516815169151701517115172151731517415175151761517715178151791518015181151821518315184151851518615187151881518915190151911519215193151941519515196151971519815199152001520115202152031520415205152061520715208152091521015211152121521315214152151521615217152181521915220152211522215223152241522515226152271522815229152301523115232152331523415235152361523715238152391524015241152421524315244152451524615247152481524915250152511525215253152541525515256152571525815259152601526115262152631526415265152661526715268152691527015271152721527315274152751527615277152781527915280152811528215283152841528515286152871528815289152901529115292152931529415295152961529715298152991530015301153021530315304153051530615307153081530915310153111531215313153141531515316153171531815319153201532115322153231532415325153261532715328153291533015331153321533315334153351533615337153381533915340153411534215343153441534515346153471534815349153501535115352153531535415355153561535715358153591536015361153621536315364153651536615367153681536915370153711537215373153741537515376153771537815379153801538115382153831538415385153861538715388153891539015391153921539315394153951539615397153981539915400154011540215403154041540515406154071540815409154101541115412154131541415415154161541715418154191542015421154221542315424154251542615427154281542915430154311543215433154341543515436154371543815439154401544115442154431544415445154461544715448154491545015451154521545315454154551545615457154581545915460154611546215463154641546515466154671546815469154701547115472154731547415475154761547715478154791548015481154821548315484154851548615487154881548915490154911549215493154941549515496154971549815499155001550115502155031550415505155061550715508155091551015511155121551315514155151551615517155181551915520155211552215523155241552515526155271552815529155301553115532155331553415535155361553715538155391554015541155421554315544155451554615547155481554915550155511555215553155541555515556155571555815559155601556115562155631556415565155661556715568155691557015571155721557315574155751557615577155781557915580155811558215583155841558515586155871558815589155901559115592155931559415595155961559715598155991560015601156021560315604156051560615607156081560915610156111561215613156141561515616156171561815619156201562115622156231562415625156261562715628156291563015631156321563315634156351563615637156381563915640156411564215643156441564515646156471564815649156501565115652156531565415655156561565715658156591566015661156621566315664156651566615667156681566915670156711567215673156741567515676156771567815679156801568115682156831568415685156861568715688156891569015691156921569315694156951569615697156981569915700157011570215703157041570515706157071570815709157101571115712157131571415715157161571715718157191572015721157221572315724157251572615727157281572915730157311573215733157341573515736157371573815739157401574115742157431574415745157461574715748157491575015751157521575315754157551575615757157581575915760157611576215763157641576515766157671576815769157701577115772157731577415775157761577715778157791578015781157821578315784157851578615787157881578915790157911579215793157941579515796157971579815799158001580115802158031580415805158061580715808158091581015811158121581315814158151581615817158181581915820158211582215823158241582515826158271582815829158301583115832158331583415835158361583715838158391584015841158421584315844158451584615847158481584915850158511585215853158541585515856158571585815859158601586115862158631586415865158661586715868158691587015871158721587315874158751587615877158781587915880158811588215883158841588515886158871588815889158901589115892158931589415895158961589715898158991590015901159021590315904159051590615907159081590915910159111591215913159141591515916159171591815919159201592115922159231592415925159261592715928159291593015931159321593315934159351593615937159381593915940159411594215943159441594515946159471594815949159501595115952159531595415955159561595715958159591596015961159621596315964159651596615967159681596915970159711597215973159741597515976159771597815979159801598115982159831598415985159861598715988159891599015991159921599315994159951599615997159981599916000160011600216003160041600516006160071600816009160101601116012160131601416015160161601716018160191602016021160221602316024160251602616027160281602916030160311603216033160341603516036160371603816039160401604116042160431604416045160461604716048160491605016051160521605316054160551605616057160581605916060160611606216063160641606516066160671606816069160701607116072160731607416075160761607716078160791608016081160821608316084160851608616087160881608916090160911609216093160941609516096160971609816099161001610116102161031610416105161061610716108161091611016111161121611316114161151611616117161181611916120161211612216123161241612516126161271612816129161301613116132161331613416135161361613716138161391614016141161421614316144161451614616147161481614916150161511615216153161541615516156161571615816159161601616116162161631616416165161661616716168161691617016171161721617316174161751617616177161781617916180161811618216183161841618516186161871618816189161901619116192161931619416195161961619716198161991620016201162021620316204162051620616207162081620916210162111621216213162141621516216162171621816219162201622116222162231622416225162261622716228162291623016231162321623316234162351623616237162381623916240162411624216243162441624516246162471624816249162501625116252162531625416255162561625716258162591626016261162621626316264162651626616267162681626916270162711627216273162741627516276162771627816279162801628116282162831628416285162861628716288162891629016291162921629316294162951629616297162981629916300163011630216303163041630516306163071630816309163101631116312163131631416315163161631716318163191632016321163221632316324163251632616327163281632916330163311633216333163341633516336163371633816339163401634116342163431634416345163461634716348163491635016351163521635316354163551635616357163581635916360163611636216363163641636516366163671636816369163701637116372163731637416375163761637716378163791638016381163821638316384163851638616387163881638916390163911639216393163941639516396163971639816399164001640116402164031640416405164061640716408164091641016411164121641316414164151641616417164181641916420164211642216423164241642516426164271642816429164301643116432164331643416435164361643716438164391644016441164421644316444164451644616447164481644916450164511645216453164541645516456164571645816459164601646116462164631646416465164661646716468164691647016471164721647316474164751647616477164781647916480164811648216483164841648516486164871648816489164901649116492164931649416495164961649716498164991650016501165021650316504165051650616507165081650916510165111651216513165141651516516165171651816519165201652116522165231652416525165261652716528165291653016531165321653316534165351653616537165381653916540165411654216543165441654516546165471654816549165501655116552165531655416555165561655716558165591656016561165621656316564165651656616567165681656916570165711657216573165741657516576165771657816579165801658116582165831658416585165861658716588165891659016591165921659316594165951659616597165981659916600166011660216603166041660516606166071660816609166101661116612166131661416615166161661716618166191662016621166221662316624166251662616627166281662916630166311663216633166341663516636166371663816639166401664116642166431664416645166461664716648166491665016651166521665316654166551665616657166581665916660166611666216663166641666516666166671666816669166701667116672166731667416675166761667716678166791668016681166821668316684166851668616687166881668916690166911669216693166941669516696166971669816699167001670116702167031670416705167061670716708167091671016711167121671316714167151671616717167181671916720167211672216723167241672516726167271672816729167301673116732167331673416735167361673716738167391674016741167421674316744167451674616747167481674916750167511675216753167541675516756167571675816759167601676116762167631676416765167661676716768167691677016771167721677316774167751677616777167781677916780167811678216783167841678516786167871678816789167901679116792167931679416795167961679716798167991680016801168021680316804168051680616807168081680916810168111681216813168141681516816168171681816819168201682116822168231682416825168261682716828168291683016831168321683316834168351683616837168381683916840168411684216843168441684516846168471684816849168501685116852168531685416855168561685716858168591686016861168621686316864168651686616867168681686916870168711687216873168741687516876168771687816879168801688116882168831688416885168861688716888168891689016891168921689316894168951689616897168981689916900169011690216903169041690516906169071690816909169101691116912169131691416915169161691716918169191692016921169221692316924169251692616927169281692916930169311693216933169341693516936169371693816939169401694116942169431694416945169461694716948169491695016951169521695316954169551695616957169581695916960169611696216963169641696516966169671696816969169701697116972169731697416975169761697716978169791698016981169821698316984169851698616987169881698916990169911699216993169941699516996169971699816999170001700117002170031700417005170061700717008170091701017011170121701317014170151701617017170181701917020170211702217023170241702517026170271702817029170301703117032170331703417035170361703717038170391704017041170421704317044170451704617047170481704917050170511705217053170541705517056170571705817059170601706117062170631706417065170661706717068170691707017071170721707317074170751707617077170781707917080170811708217083170841708517086170871708817089170901709117092170931709417095170961709717098170991710017101171021710317104171051710617107171081710917110171111711217113171141711517116171171711817119171201712117122171231712417125171261712717128171291713017131171321713317134171351713617137171381713917140171411714217143171441714517146171471714817149171501715117152171531715417155171561715717158171591716017161171621716317164171651716617167171681716917170171711717217173171741717517176171771717817179171801718117182171831718417185171861718717188171891719017191171921719317194171951719617197171981719917200172011720217203172041720517206172071720817209172101721117212172131721417215172161721717218172191722017221172221722317224172251722617227172281722917230172311723217233172341723517236172371723817239172401724117242172431724417245172461724717248172491725017251172521725317254172551725617257172581725917260172611726217263172641726517266172671726817269172701727117272172731727417275172761727717278172791728017281172821728317284172851728617287172881728917290172911729217293172941729517296172971729817299173001730117302173031730417305173061730717308173091731017311173121731317314173151731617317173181731917320173211732217323173241732517326173271732817329173301733117332173331733417335173361733717338173391734017341173421734317344173451734617347173481734917350173511735217353173541735517356173571735817359173601736117362173631736417365173661736717368173691737017371173721737317374173751737617377173781737917380173811738217383173841738517386173871738817389173901739117392173931739417395173961739717398173991740017401174021740317404174051740617407174081740917410174111741217413174141741517416174171741817419174201742117422174231742417425174261742717428174291743017431174321743317434174351743617437174381743917440174411744217443174441744517446174471744817449174501745117452174531745417455174561745717458174591746017461174621746317464174651746617467174681746917470174711747217473174741747517476174771747817479174801748117482174831748417485174861748717488174891749017491174921749317494174951749617497174981749917500175011750217503175041750517506175071750817509175101751117512175131751417515175161751717518175191752017521175221752317524175251752617527175281752917530175311753217533175341753517536175371753817539175401754117542175431754417545175461754717548175491755017551175521755317554175551755617557175581755917560175611756217563175641756517566175671756817569175701757117572175731757417575175761757717578175791758017581175821758317584175851758617587175881758917590175911759217593175941759517596175971759817599176001760117602176031760417605176061760717608176091761017611176121761317614176151761617617176181761917620176211762217623176241762517626176271762817629176301763117632176331763417635176361763717638176391764017641176421764317644176451764617647176481764917650176511765217653176541765517656176571765817659176601766117662176631766417665176661766717668176691767017671176721767317674176751767617677176781767917680176811768217683176841768517686176871768817689176901769117692176931769417695176961769717698176991770017701177021770317704177051770617707177081770917710177111771217713177141771517716177171771817719177201772117722177231772417725177261772717728177291773017731177321773317734177351773617737177381773917740177411774217743177441774517746177471774817749177501775117752177531775417755177561775717758177591776017761177621776317764177651776617767177681776917770177711777217773177741777517776177771777817779177801778117782177831778417785177861778717788177891779017791177921779317794177951779617797177981779917800178011780217803178041780517806178071780817809178101781117812178131781417815178161781717818178191782017821178221782317824178251782617827178281782917830178311783217833178341783517836178371783817839178401784117842178431784417845178461784717848178491785017851178521785317854178551785617857178581785917860178611786217863178641786517866178671786817869178701787117872178731787417875178761787717878178791788017881178821788317884178851788617887178881788917890178911789217893178941789517896178971789817899179001790117902179031790417905179061790717908179091791017911179121791317914179151791617917179181791917920179211792217923179241792517926179271792817929179301793117932179331793417935179361793717938179391794017941179421794317944179451794617947179481794917950179511795217953179541795517956179571795817959179601796117962179631796417965179661796717968179691797017971179721797317974179751797617977179781797917980179811798217983179841798517986179871798817989179901799117992179931799417995179961799717998179991800018001180021800318004180051800618007180081800918010180111801218013180141801518016180171801818019180201802118022180231802418025180261802718028180291803018031180321803318034180351803618037180381803918040180411804218043180441804518046180471804818049180501805118052180531805418055180561805718058180591806018061180621806318064180651806618067180681806918070180711807218073180741807518076180771807818079180801808118082180831808418085180861808718088180891809018091180921809318094180951809618097180981809918100181011810218103181041810518106181071810818109181101811118112181131811418115181161811718118181191812018121181221812318124181251812618127181281812918130181311813218133181341813518136181371813818139181401814118142181431814418145181461814718148181491815018151181521815318154181551815618157181581815918160181611816218163181641816518166181671816818169181701817118172181731817418175181761817718178181791818018181181821818318184181851818618187181881818918190181911819218193181941819518196181971819818199182001820118202182031820418205182061820718208182091821018211182121821318214182151821618217182181821918220182211822218223182241822518226182271822818229182301823118232182331823418235182361823718238182391824018241182421824318244182451824618247182481824918250182511825218253182541825518256182571825818259182601826118262182631826418265182661826718268182691827018271182721827318274182751827618277182781827918280182811828218283182841828518286182871828818289182901829118292182931829418295182961829718298182991830018301183021830318304183051830618307183081830918310183111831218313183141831518316183171831818319183201832118322183231832418325183261832718328183291833018331183321833318334183351833618337183381833918340183411834218343183441834518346183471834818349183501835118352183531835418355183561835718358183591836018361183621836318364183651836618367183681836918370183711837218373183741837518376183771837818379183801838118382183831838418385183861838718388183891839018391183921839318394183951839618397183981839918400184011840218403184041840518406184071840818409184101841118412184131841418415184161841718418184191842018421184221842318424184251842618427184281842918430184311843218433184341843518436184371843818439184401844118442184431844418445184461844718448184491845018451184521845318454184551845618457184581845918460184611846218463184641846518466184671846818469184701847118472184731847418475184761847718478184791848018481184821848318484184851848618487184881848918490184911849218493184941849518496184971849818499185001850118502185031850418505185061850718508185091851018511185121851318514185151851618517185181851918520185211852218523185241852518526185271852818529185301853118532185331853418535185361853718538185391854018541185421854318544185451854618547185481854918550185511855218553185541855518556185571855818559185601856118562185631856418565185661856718568185691857018571185721857318574185751857618577185781857918580185811858218583185841858518586185871858818589185901859118592185931859418595185961859718598185991860018601186021860318604186051860618607186081860918610186111861218613186141861518616186171861818619186201862118622186231862418625186261862718628186291863018631186321863318634186351863618637186381863918640186411864218643186441864518646186471864818649186501865118652186531865418655186561865718658186591866018661186621866318664186651866618667186681866918670186711867218673186741867518676186771867818679186801868118682186831868418685186861868718688186891869018691186921869318694186951869618697186981869918700187011870218703187041870518706187071870818709187101871118712187131871418715187161871718718187191872018721187221872318724187251872618727187281872918730187311873218733187341873518736187371873818739187401874118742187431874418745187461874718748187491875018751187521875318754187551875618757187581875918760187611876218763187641876518766187671876818769187701877118772187731877418775187761877718778187791878018781187821878318784187851878618787187881878918790187911879218793187941879518796187971879818799188001880118802188031880418805188061880718808188091881018811188121881318814188151881618817188181881918820188211882218823188241882518826188271882818829188301883118832188331883418835188361883718838188391884018841188421884318844188451884618847188481884918850188511885218853188541885518856188571885818859188601886118862188631886418865188661886718868188691887018871188721887318874188751887618877188781887918880188811888218883188841888518886188871888818889188901889118892188931889418895188961889718898188991890018901189021890318904189051890618907189081890918910189111891218913189141891518916189171891818919189201892118922189231892418925189261892718928189291893018931189321893318934189351893618937189381893918940189411894218943189441894518946189471894818949189501895118952189531895418955189561895718958189591896018961189621896318964189651896618967189681896918970189711897218973189741897518976189771897818979189801898118982189831898418985189861898718988189891899018991189921899318994189951899618997189981899919000190011900219003190041900519006190071900819009190101901119012190131901419015190161901719018190191902019021190221902319024190251902619027190281902919030190311903219033190341903519036190371903819039190401904119042190431904419045190461904719048190491905019051190521905319054190551905619057190581905919060190611906219063190641906519066190671906819069190701907119072190731907419075190761907719078190791908019081190821908319084190851908619087190881908919090190911909219093190941909519096190971909819099191001910119102191031910419105191061910719108191091911019111191121911319114191151911619117191181911919120191211912219123191241912519126191271912819129191301913119132191331913419135191361913719138191391914019141191421914319144191451914619147191481914919150191511915219153191541915519156191571915819159191601916119162191631916419165191661916719168191691917019171191721917319174191751917619177191781917919180191811918219183191841918519186191871918819189191901919119192191931919419195191961919719198191991920019201192021920319204192051920619207192081920919210192111921219213192141921519216192171921819219192201922119222192231922419225192261922719228192291923019231192321923319234192351923619237192381923919240192411924219243192441924519246192471924819249192501925119252192531925419255192561925719258192591926019261192621926319264192651926619267192681926919270192711927219273192741927519276192771927819279192801928119282192831928419285192861928719288192891929019291192921929319294192951929619297192981929919300193011930219303193041930519306193071930819309193101931119312193131931419315193161931719318193191932019321193221932319324193251932619327193281932919330193311933219333193341933519336193371933819339193401934119342193431934419345193461934719348193491935019351193521935319354193551935619357193581935919360193611936219363193641936519366193671936819369193701937119372193731937419375193761937719378193791938019381193821938319384193851938619387193881938919390193911939219393193941939519396193971939819399194001940119402194031940419405194061940719408194091941019411194121941319414194151941619417194181941919420194211942219423194241942519426194271942819429194301943119432194331943419435194361943719438194391944019441194421944319444194451944619447194481944919450194511945219453194541945519456194571945819459194601946119462194631946419465194661946719468194691947019471194721947319474194751947619477194781947919480194811948219483194841948519486194871948819489194901949119492194931949419495194961949719498194991950019501195021950319504195051950619507195081950919510195111951219513195141951519516195171951819519195201952119522195231952419525195261952719528195291953019531195321953319534195351953619537195381953919540195411954219543195441954519546195471954819549195501955119552195531955419555195561955719558195591956019561195621956319564195651956619567195681956919570195711957219573195741957519576195771957819579195801958119582195831958419585195861958719588195891959019591195921959319594195951959619597195981959919600196011960219603196041960519606196071960819609196101961119612196131961419615196161961719618196191962019621196221962319624196251962619627196281962919630196311963219633196341963519636196371963819639196401964119642196431964419645196461964719648196491965019651196521965319654196551965619657196581965919660196611966219663196641966519666196671966819669196701967119672196731967419675196761967719678196791968019681196821968319684196851968619687196881968919690196911969219693196941969519696196971969819699197001970119702197031970419705197061970719708197091971019711197121971319714197151971619717197181971919720197211972219723197241972519726197271972819729197301973119732197331973419735197361973719738197391974019741197421974319744197451974619747197481974919750197511975219753197541975519756197571975819759197601976119762197631976419765197661976719768197691977019771197721977319774197751977619777197781977919780197811978219783197841978519786197871978819789197901979119792197931979419795197961979719798197991980019801198021980319804198051980619807198081980919810198111981219813198141981519816198171981819819198201982119822198231982419825198261982719828198291983019831198321983319834198351983619837198381983919840198411984219843198441984519846198471984819849198501985119852198531985419855198561985719858198591986019861198621986319864198651986619867198681986919870198711987219873198741987519876198771987819879198801988119882198831988419885198861988719888198891989019891198921989319894198951989619897198981989919900199011990219903199041990519906199071990819909199101991119912199131991419915199161991719918199191992019921199221992319924199251992619927199281992919930199311993219933199341993519936199371993819939199401994119942199431994419945199461994719948199491995019951199521995319954199551995619957199581995919960199611996219963199641996519966199671996819969199701997119972199731997419975199761997719978199791998019981199821998319984199851998619987199881998919990199911999219993199941999519996199971999819999200002000120002200032000420005200062000720008200092001020011200122001320014200152001620017200182001920020200212002220023200242002520026200272002820029200302003120032200332003420035200362003720038200392004020041200422004320044200452004620047200482004920050200512005220053200542005520056200572005820059200602006120062200632006420065200662006720068200692007020071200722007320074200752007620077200782007920080200812008220083200842008520086200872008820089200902009120092200932009420095200962009720098200992010020101201022010320104201052010620107201082010920110201112011220113201142011520116201172011820119201202012120122201232012420125201262012720128201292013020131201322013320134201352013620137201382013920140201412014220143201442014520146201472014820149201502015120152201532015420155201562015720158201592016020161201622016320164201652016620167201682016920170201712017220173201742017520176201772017820179201802018120182201832018420185201862018720188201892019020191201922019320194201952019620197201982019920200202012020220203202042020520206202072020820209202102021120212202132021420215202162021720218202192022020221202222022320224202252022620227202282022920230202312023220233202342023520236202372023820239202402024120242202432024420245202462024720248202492025020251202522025320254202552025620257202582025920260202612026220263202642026520266202672026820269202702027120272202732027420275202762027720278202792028020281202822028320284202852028620287202882028920290202912029220293202942029520296202972029820299203002030120302203032030420305203062030720308203092031020311203122031320314203152031620317203182031920320203212032220323203242032520326203272032820329203302033120332203332033420335203362033720338203392034020341203422034320344203452034620347203482034920350203512035220353203542035520356203572035820359203602036120362203632036420365203662036720368203692037020371203722037320374203752037620377203782037920380203812038220383203842038520386203872038820389203902039120392203932039420395203962039720398203992040020401204022040320404204052040620407204082040920410204112041220413204142041520416204172041820419204202042120422204232042420425204262042720428204292043020431204322043320434204352043620437204382043920440204412044220443204442044520446204472044820449204502045120452204532045420455204562045720458204592046020461204622046320464204652046620467204682046920470204712047220473204742047520476204772047820479204802048120482204832048420485204862048720488204892049020491204922049320494204952049620497204982049920500205012050220503205042050520506205072050820509205102051120512205132051420515205162051720518205192052020521205222052320524205252052620527205282052920530205312053220533205342053520536205372053820539205402054120542205432054420545205462054720548205492055020551205522055320554205552055620557205582055920560205612056220563205642056520566205672056820569205702057120572205732057420575205762057720578205792058020581205822058320584205852058620587205882058920590205912059220593205942059520596205972059820599206002060120602206032060420605206062060720608206092061020611206122061320614206152061620617206182061920620206212062220623206242062520626206272062820629206302063120632206332063420635206362063720638206392064020641206422064320644206452064620647206482064920650206512065220653206542065520656206572065820659206602066120662206632066420665206662066720668206692067020671206722067320674206752067620677206782067920680206812068220683206842068520686206872068820689206902069120692206932069420695206962069720698206992070020701207022070320704207052070620707207082070920710207112071220713207142071520716207172071820719207202072120722207232072420725207262072720728207292073020731207322073320734207352073620737207382073920740207412074220743207442074520746207472074820749207502075120752207532075420755207562075720758207592076020761207622076320764207652076620767207682076920770207712077220773207742077520776207772077820779207802078120782207832078420785207862078720788207892079020791207922079320794207952079620797207982079920800208012080220803208042080520806208072080820809208102081120812208132081420815208162081720818208192082020821208222082320824208252082620827208282082920830208312083220833208342083520836208372083820839208402084120842208432084420845208462084720848208492085020851208522085320854208552085620857208582085920860208612086220863208642086520866208672086820869208702087120872208732087420875208762087720878208792088020881208822088320884208852088620887208882088920890208912089220893208942089520896208972089820899209002090120902209032090420905209062090720908209092091020911209122091320914209152091620917209182091920920209212092220923209242092520926209272092820929209302093120932209332093420935209362093720938209392094020941209422094320944209452094620947209482094920950209512095220953209542095520956209572095820959209602096120962209632096420965209662096720968209692097020971209722097320974209752097620977209782097920980209812098220983209842098520986209872098820989209902099120992209932099420995209962099720998209992100021001210022100321004210052100621007210082100921010210112101221013210142101521016210172101821019210202102121022210232102421025210262102721028210292103021031210322103321034210352103621037210382103921040210412104221043210442104521046210472104821049210502105121052210532105421055210562105721058210592106021061210622106321064210652106621067210682106921070210712107221073210742107521076210772107821079210802108121082210832108421085210862108721088210892109021091210922109321094210952109621097210982109921100211012110221103211042110521106211072110821109211102111121112211132111421115211162111721118211192112021121211222112321124211252112621127211282112921130211312113221133211342113521136211372113821139211402114121142211432114421145211462114721148211492115021151211522115321154211552115621157211582115921160211612116221163211642116521166211672116821169211702117121172211732117421175211762117721178211792118021181211822118321184211852118621187211882118921190211912119221193211942119521196211972119821199212002120121202212032120421205212062120721208212092121021211212122121321214212152121621217212182121921220212212122221223212242122521226212272122821229212302123121232212332123421235212362123721238212392124021241212422124321244212452124621247212482124921250212512125221253212542125521256212572125821259212602126121262212632126421265212662126721268212692127021271212722127321274212752127621277212782127921280212812128221283212842128521286212872128821289212902129121292212932129421295212962129721298212992130021301213022130321304213052130621307213082130921310213112131221313213142131521316213172131821319213202132121322213232132421325213262132721328213292133021331213322133321334213352133621337213382133921340213412134221343213442134521346213472134821349213502135121352213532135421355213562135721358213592136021361213622136321364213652136621367213682136921370213712137221373213742137521376213772137821379213802138121382213832138421385213862138721388213892139021391213922139321394213952139621397213982139921400214012140221403214042140521406214072140821409214102141121412214132141421415214162141721418214192142021421214222142321424214252142621427214282142921430214312143221433214342143521436214372143821439214402144121442214432144421445214462144721448214492145021451214522145321454214552145621457214582145921460214612146221463214642146521466214672146821469214702147121472214732147421475214762147721478214792148021481214822148321484214852148621487214882148921490214912149221493214942149521496214972149821499215002150121502215032150421505215062150721508215092151021511215122151321514215152151621517215182151921520215212152221523215242152521526215272152821529215302153121532215332153421535215362153721538215392154021541215422154321544215452154621547215482154921550215512155221553215542155521556215572155821559215602156121562215632156421565215662156721568215692157021571215722157321574215752157621577215782157921580215812158221583215842158521586215872158821589215902159121592215932159421595215962159721598215992160021601216022160321604216052160621607216082160921610216112161221613216142161521616216172161821619216202162121622216232162421625216262162721628216292163021631216322163321634216352163621637216382163921640216412164221643216442164521646216472164821649216502165121652216532165421655216562165721658216592166021661216622166321664216652166621667216682166921670216712167221673216742167521676216772167821679216802168121682216832168421685216862168721688216892169021691216922169321694216952169621697216982169921700217012170221703217042170521706217072170821709217102171121712217132171421715217162171721718217192172021721217222172321724217252172621727217282172921730217312173221733217342173521736217372173821739217402174121742217432174421745217462174721748217492175021751217522175321754217552175621757217582175921760217612176221763217642176521766217672176821769217702177121772217732177421775217762177721778217792178021781217822178321784217852178621787217882178921790217912179221793217942179521796217972179821799218002180121802218032180421805218062180721808218092181021811218122181321814218152181621817218182181921820218212182221823218242182521826218272182821829218302183121832218332183421835218362183721838218392184021841218422184321844218452184621847218482184921850218512185221853218542185521856218572185821859218602186121862218632186421865218662186721868218692187021871218722187321874218752187621877218782187921880218812188221883218842188521886218872188821889218902189121892218932189421895218962189721898218992190021901219022190321904219052190621907219082190921910219112191221913219142191521916219172191821919219202192121922219232192421925219262192721928219292193021931219322193321934219352193621937219382193921940219412194221943219442194521946219472194821949219502195121952219532195421955219562195721958219592196021961219622196321964219652196621967219682196921970219712197221973219742197521976219772197821979219802198121982219832198421985219862198721988219892199021991219922199321994219952199621997219982199922000220012200222003220042200522006220072200822009220102201122012220132201422015220162201722018220192202022021220222202322024220252202622027220282202922030220312203222033220342203522036220372203822039220402204122042220432204422045220462204722048220492205022051220522205322054220552205622057220582205922060220612206222063220642206522066220672206822069220702207122072220732207422075220762207722078220792208022081220822208322084220852208622087220882208922090220912209222093220942209522096220972209822099221002210122102221032210422105221062210722108221092211022111221122211322114221152211622117221182211922120221212212222123221242212522126221272212822129221302213122132221332213422135221362213722138221392214022141221422214322144221452214622147221482214922150221512215222153221542215522156221572215822159221602216122162221632216422165221662216722168221692217022171221722217322174221752217622177221782217922180221812218222183221842218522186221872218822189221902219122192221932219422195221962219722198221992220022201222022220322204222052220622207222082220922210222112221222213222142221522216222172221822219222202222122222222232222422225222262222722228222292223022231222322223322234222352223622237222382223922240222412224222243222442224522246222472224822249222502225122252222532225422255222562225722258222592226022261222622226322264222652226622267222682226922270222712227222273222742227522276222772227822279222802228122282222832228422285222862228722288222892229022291222922229322294222952229622297222982229922300223012230222303223042230522306223072230822309223102231122312223132231422315223162231722318223192232022321223222232322324223252232622327223282232922330223312233222333223342233522336223372233822339223402234122342223432234422345223462234722348223492235022351223522235322354223552235622357223582235922360223612236222363223642236522366223672236822369223702237122372223732237422375223762237722378223792238022381223822238322384223852238622387223882238922390223912239222393223942239522396223972239822399224002240122402224032240422405224062240722408224092241022411224122241322414224152241622417224182241922420224212242222423224242242522426224272242822429224302243122432224332243422435224362243722438224392244022441224422244322444224452244622447224482244922450224512245222453224542245522456224572245822459224602246122462224632246422465224662246722468224692247022471224722247322474224752247622477224782247922480224812248222483224842248522486224872248822489224902249122492224932249422495224962249722498224992250022501225022250322504225052250622507225082250922510225112251222513225142251522516225172251822519225202252122522225232252422525225262252722528225292253022531225322253322534225352253622537225382253922540225412254222543225442254522546225472254822549225502255122552225532255422555225562255722558225592256022561225622256322564225652256622567225682256922570225712257222573225742257522576225772257822579225802258122582225832258422585225862258722588225892259022591225922259322594225952259622597225982259922600226012260222603226042260522606226072260822609226102261122612226132261422615226162261722618226192262022621226222262322624226252262622627226282262922630226312263222633226342263522636226372263822639226402264122642226432264422645226462264722648226492265022651226522265322654226552265622657226582265922660226612266222663226642266522666226672266822669226702267122672226732267422675226762267722678226792268022681226822268322684226852268622687226882268922690226912269222693226942269522696226972269822699227002270122702227032270422705227062270722708227092271022711227122271322714227152271622717227182271922720227212272222723227242272522726227272272822729227302273122732227332273422735227362273722738227392274022741227422274322744227452274622747227482274922750227512275222753227542275522756227572275822759227602276122762227632276422765227662276722768227692277022771227722277322774227752277622777227782277922780227812278222783227842278522786227872278822789227902279122792227932279422795227962279722798227992280022801228022280322804228052280622807228082280922810228112281222813228142281522816228172281822819228202282122822228232282422825228262282722828228292283022831228322283322834228352283622837228382283922840228412284222843228442284522846228472284822849228502285122852228532285422855228562285722858228592286022861228622286322864228652286622867228682286922870228712287222873228742287522876228772287822879228802288122882228832288422885228862288722888228892289022891228922289322894228952289622897228982289922900229012290222903229042290522906229072290822909229102291122912229132291422915229162291722918229192292022921229222292322924229252292622927229282292922930229312293222933229342293522936229372293822939229402294122942229432294422945229462294722948229492295022951229522295322954229552295622957229582295922960229612296222963229642296522966229672296822969229702297122972229732297422975229762297722978229792298022981229822298322984229852298622987229882298922990229912299222993229942299522996229972299822999230002300123002230032300423005230062300723008230092301023011230122301323014230152301623017230182301923020230212302223023230242302523026230272302823029230302303123032230332303423035230362303723038230392304023041230422304323044230452304623047230482304923050230512305223053230542305523056230572305823059230602306123062230632306423065230662306723068230692307023071230722307323074230752307623077230782307923080230812308223083230842308523086230872308823089230902309123092230932309423095230962309723098230992310023101231022310323104231052310623107231082310923110231112311223113231142311523116231172311823119231202312123122231232312423125231262312723128231292313023131231322313323134231352313623137231382313923140231412314223143231442314523146231472314823149231502315123152231532315423155231562315723158231592316023161231622316323164231652316623167231682316923170231712317223173231742317523176231772317823179231802318123182231832318423185231862318723188231892319023191231922319323194231952319623197231982319923200232012320223203232042320523206232072320823209232102321123212232132321423215232162321723218232192322023221232222322323224232252322623227232282322923230232312323223233232342323523236232372323823239232402324123242232432324423245232462324723248232492325023251232522325323254232552325623257232582325923260232612326223263232642326523266232672326823269232702327123272232732327423275232762327723278232792328023281232822328323284232852328623287232882328923290232912329223293232942329523296232972329823299233002330123302233032330423305233062330723308233092331023311233122331323314233152331623317233182331923320233212332223323233242332523326233272332823329233302333123332233332333423335233362333723338233392334023341233422334323344233452334623347233482334923350233512335223353233542335523356233572335823359233602336123362233632336423365233662336723368233692337023371233722337323374233752337623377233782337923380233812338223383233842338523386233872338823389233902339123392233932339423395233962339723398233992340023401234022340323404234052340623407234082340923410234112341223413234142341523416234172341823419234202342123422234232342423425234262342723428234292343023431234322343323434234352343623437234382343923440234412344223443234442344523446234472344823449234502345123452234532345423455234562345723458234592346023461234622346323464234652346623467234682346923470234712347223473234742347523476234772347823479234802348123482234832348423485234862348723488234892349023491234922349323494234952349623497234982349923500235012350223503235042350523506235072350823509235102351123512235132351423515235162351723518235192352023521235222352323524235252352623527235282352923530235312353223533235342353523536235372353823539235402354123542235432354423545235462354723548235492355023551235522355323554235552355623557235582355923560235612356223563235642356523566235672356823569235702357123572235732357423575235762357723578235792358023581235822358323584235852358623587235882358923590235912359223593235942359523596235972359823599236002360123602236032360423605236062360723608236092361023611236122361323614236152361623617236182361923620236212362223623236242362523626236272362823629236302363123632236332363423635236362363723638236392364023641236422364323644236452364623647236482364923650236512365223653236542365523656236572365823659236602366123662236632366423665236662366723668236692367023671236722367323674236752367623677236782367923680236812368223683236842368523686236872368823689236902369123692236932369423695236962369723698236992370023701237022370323704237052370623707237082370923710237112371223713237142371523716237172371823719237202372123722237232372423725237262372723728237292373023731237322373323734237352373623737237382373923740237412374223743237442374523746237472374823749237502375123752237532375423755237562375723758237592376023761237622376323764237652376623767237682376923770237712377223773237742377523776237772377823779237802378123782237832378423785237862378723788237892379023791237922379323794237952379623797237982379923800238012380223803238042380523806238072380823809238102381123812238132381423815238162381723818238192382023821238222382323824238252382623827238282382923830238312383223833238342383523836238372383823839238402384123842238432384423845238462384723848238492385023851238522385323854238552385623857238582385923860238612386223863238642386523866238672386823869238702387123872238732387423875238762387723878238792388023881238822388323884238852388623887238882388923890238912389223893238942389523896238972389823899239002390123902239032390423905239062390723908239092391023911239122391323914239152391623917239182391923920239212392223923239242392523926239272392823929239302393123932239332393423935239362393723938239392394023941239422394323944239452394623947239482394923950239512395223953239542395523956239572395823959239602396123962239632396423965239662396723968239692397023971239722397323974239752397623977239782397923980239812398223983239842398523986239872398823989239902399123992239932399423995239962399723998239992400024001240022400324004240052400624007240082400924010240112401224013240142401524016240172401824019240202402124022240232402424025240262402724028240292403024031240322403324034240352403624037240382403924040240412404224043240442404524046240472404824049240502405124052240532405424055240562405724058240592406024061240622406324064240652406624067240682406924070240712407224073240742407524076240772407824079240802408124082240832408424085240862408724088240892409024091240922409324094240952409624097240982409924100241012410224103241042410524106241072410824109241102411124112241132411424115241162411724118241192412024121241222412324124241252412624127241282412924130241312413224133241342413524136241372413824139241402414124142241432414424145241462414724148241492415024151241522415324154241552415624157241582415924160241612416224163241642416524166241672416824169241702417124172241732417424175241762417724178241792418024181241822418324184241852418624187241882418924190241912419224193241942419524196241972419824199242002420124202242032420424205242062420724208242092421024211242122421324214242152421624217242182421924220242212422224223242242422524226242272422824229242302423124232242332423424235242362423724238242392424024241242422424324244242452424624247242482424924250242512425224253242542425524256242572425824259242602426124262242632426424265242662426724268242692427024271242722427324274242752427624277242782427924280242812428224283242842428524286242872428824289242902429124292242932429424295242962429724298242992430024301243022430324304243052430624307243082430924310243112431224313243142431524316243172431824319243202432124322243232432424325243262432724328243292433024331243322433324334243352433624337243382433924340243412434224343243442434524346243472434824349243502435124352243532435424355243562435724358243592436024361243622436324364243652436624367243682436924370243712437224373243742437524376243772437824379243802438124382243832438424385243862438724388243892439024391243922439324394243952439624397243982439924400244012440224403244042440524406244072440824409244102441124412244132441424415244162441724418244192442024421244222442324424244252442624427244282442924430244312443224433244342443524436244372443824439244402444124442244432444424445244462444724448244492445024451244522445324454244552445624457244582445924460244612446224463244642446524466244672446824469244702447124472244732447424475244762447724478244792448024481244822448324484244852448624487244882448924490244912449224493244942449524496244972449824499245002450124502245032450424505245062450724508245092451024511245122451324514245152451624517245182451924520245212452224523245242452524526245272452824529245302453124532245332453424535245362453724538245392454024541245422454324544245452454624547245482454924550245512455224553245542455524556245572455824559245602456124562245632456424565245662456724568245692457024571245722457324574245752457624577245782457924580245812458224583245842458524586245872458824589245902459124592245932459424595245962459724598245992460024601246022460324604246052460624607246082460924610246112461224613246142461524616246172461824619246202462124622246232462424625246262462724628246292463024631246322463324634246352463624637246382463924640246412464224643246442464524646246472464824649246502465124652246532465424655246562465724658246592466024661246622466324664246652466624667246682466924670246712467224673246742467524676246772467824679246802468124682246832468424685246862468724688246892469024691246922469324694246952469624697246982469924700247012470224703247042470524706247072470824709247102471124712247132471424715247162471724718247192472024721247222472324724247252472624727247282472924730247312473224733247342473524736247372473824739247402474124742247432474424745247462474724748247492475024751247522475324754247552475624757247582475924760247612476224763247642476524766247672476824769247702477124772247732477424775247762477724778247792478024781247822478324784247852478624787247882478924790247912479224793247942479524796247972479824799248002480124802248032480424805248062480724808248092481024811248122481324814248152481624817248182481924820248212482224823248242482524826248272482824829248302483124832248332483424835248362483724838248392484024841248422484324844248452484624847248482484924850248512485224853248542485524856248572485824859248602486124862248632486424865248662486724868248692487024871248722487324874248752487624877248782487924880248812488224883248842488524886248872488824889248902489124892248932489424895248962489724898248992490024901249022490324904249052490624907249082490924910249112491224913249142491524916249172491824919249202492124922249232492424925249262492724928249292493024931249322493324934249352493624937249382493924940249412494224943249442494524946249472494824949249502495124952249532495424955249562495724958249592496024961249622496324964249652496624967249682496924970249712497224973249742497524976249772497824979249802498124982249832498424985249862498724988249892499024991249922499324994249952499624997249982499925000250012500225003250042500525006250072500825009250102501125012250132501425015250162501725018250192502025021250222502325024250252502625027250282502925030250312503225033250342503525036250372503825039250402504125042250432504425045250462504725048250492505025051250522505325054250552505625057250582505925060250612506225063250642506525066250672506825069250702507125072250732507425075250762507725078250792508025081250822508325084250852508625087250882508925090250912509225093250942509525096250972509825099251002510125102251032510425105251062510725108251092511025111251122511325114251152511625117251182511925120251212512225123251242512525126251272512825129251302513125132251332513425135251362513725138251392514025141251422514325144251452514625147251482514925150251512515225153251542515525156251572515825159251602516125162251632516425165251662516725168251692517025171251722517325174251752517625177251782517925180251812518225183251842518525186251872518825189251902519125192251932519425195251962519725198251992520025201252022520325204252052520625207252082520925210252112521225213252142521525216252172521825219252202522125222252232522425225252262522725228252292523025231252322523325234252352523625237252382523925240252412524225243252442524525246252472524825249252502525125252252532525425255252562525725258252592526025261252622526325264252652526625267252682526925270252712527225273252742527525276252772527825279252802528125282252832528425285252862528725288252892529025291252922529325294252952529625297252982529925300253012530225303253042530525306253072530825309253102531125312253132531425315253162531725318253192532025321253222532325324253252532625327253282532925330253312533225333253342533525336253372533825339253402534125342253432534425345253462534725348253492535025351253522535325354253552535625357253582535925360253612536225363253642536525366253672536825369253702537125372253732537425375253762537725378253792538025381253822538325384253852538625387253882538925390253912539225393253942539525396253972539825399254002540125402254032540425405254062540725408254092541025411254122541325414254152541625417254182541925420254212542225423254242542525426254272542825429254302543125432254332543425435254362543725438254392544025441254422544325444254452544625447254482544925450254512545225453254542545525456254572545825459254602546125462254632546425465254662546725468254692547025471254722547325474254752547625477254782547925480254812548225483254842548525486254872548825489254902549125492254932549425495254962549725498254992550025501255022550325504255052550625507255082550925510255112551225513255142551525516255172551825519255202552125522255232552425525255262552725528255292553025531255322553325534255352553625537255382553925540255412554225543255442554525546255472554825549255502555125552255532555425555255562555725558255592556025561255622556325564255652556625567255682556925570255712557225573255742557525576255772557825579255802558125582255832558425585255862558725588255892559025591255922559325594255952559625597255982559925600256012560225603256042560525606256072560825609256102561125612256132561425615256162561725618256192562025621256222562325624256252562625627256282562925630256312563225633256342563525636256372563825639256402564125642256432564425645256462564725648256492565025651256522565325654256552565625657256582565925660256612566225663256642566525666256672566825669256702567125672256732567425675256762567725678256792568025681256822568325684256852568625687256882568925690256912569225693256942569525696256972569825699257002570125702257032570425705257062570725708257092571025711257122571325714257152571625717257182571925720257212572225723257242572525726257272572825729257302573125732257332573425735257362573725738257392574025741257422574325744257452574625747257482574925750257512575225753257542575525756257572575825759257602576125762257632576425765257662576725768257692577025771257722577325774257752577625777257782577925780257812578225783257842578525786257872578825789257902579125792257932579425795257962579725798257992580025801258022580325804258052580625807258082580925810258112581225813258142581525816258172581825819258202582125822258232582425825258262582725828258292583025831258322583325834258352583625837258382583925840258412584225843258442584525846258472584825849258502585125852258532585425855258562585725858258592586025861258622586325864258652586625867258682586925870258712587225873258742587525876258772587825879258802588125882258832588425885258862588725888258892589025891258922589325894258952589625897258982589925900259012590225903259042590525906259072590825909259102591125912259132591425915259162591725918259192592025921259222592325924259252592625927259282592925930259312593225933259342593525936259372593825939259402594125942259432594425945259462594725948259492595025951259522595325954259552595625957259582595925960259612596225963259642596525966259672596825969259702597125972259732597425975259762597725978259792598025981259822598325984259852598625987259882598925990259912599225993259942599525996259972599825999260002600126002260032600426005260062600726008260092601026011260122601326014260152601626017260182601926020260212602226023260242602526026260272602826029260302603126032260332603426035260362603726038260392604026041260422604326044260452604626047260482604926050260512605226053260542605526056260572605826059260602606126062260632606426065260662606726068260692607026071260722607326074260752607626077260782607926080260812608226083260842608526086260872608826089260902609126092260932609426095260962609726098260992610026101261022610326104261052610626107261082610926110261112611226113261142611526116261172611826119261202612126122261232612426125261262612726128261292613026131261322613326134261352613626137261382613926140261412614226143261442614526146261472614826149261502615126152261532615426155261562615726158261592616026161261622616326164261652616626167261682616926170261712617226173261742617526176261772617826179261802618126182261832618426185261862618726188261892619026191261922619326194261952619626197261982619926200262012620226203262042620526206262072620826209262102621126212262132621426215262162621726218262192622026221262222622326224262252622626227262282622926230262312623226233262342623526236262372623826239262402624126242262432624426245262462624726248262492625026251262522625326254262552625626257262582625926260262612626226263262642626526266262672626826269262702627126272262732627426275262762627726278262792628026281262822628326284262852628626287262882628926290262912629226293262942629526296262972629826299263002630126302263032630426305263062630726308263092631026311263122631326314263152631626317263182631926320263212632226323263242632526326263272632826329263302633126332263332633426335263362633726338263392634026341263422634326344263452634626347263482634926350263512635226353263542635526356263572635826359263602636126362263632636426365263662636726368263692637026371263722637326374263752637626377263782637926380263812638226383263842638526386263872638826389263902639126392263932639426395263962639726398263992640026401264022640326404264052640626407264082640926410264112641226413264142641526416264172641826419264202642126422264232642426425264262642726428264292643026431264322643326434264352643626437264382643926440264412644226443264442644526446264472644826449264502645126452264532645426455264562645726458264592646026461264622646326464264652646626467264682646926470264712647226473264742647526476264772647826479264802648126482264832648426485264862648726488264892649026491264922649326494264952649626497264982649926500265012650226503265042650526506265072650826509265102651126512265132651426515265162651726518265192652026521265222652326524265252652626527265282652926530265312653226533265342653526536265372653826539265402654126542265432654426545265462654726548265492655026551265522655326554265552655626557265582655926560265612656226563265642656526566265672656826569265702657126572265732657426575265762657726578265792658026581265822658326584265852658626587265882658926590265912659226593265942659526596265972659826599266002660126602266032660426605266062660726608266092661026611266122661326614266152661626617266182661926620266212662226623266242662526626266272662826629266302663126632266332663426635266362663726638266392664026641266422664326644266452664626647266482664926650266512665226653266542665526656266572665826659266602666126662266632666426665266662666726668266692667026671266722667326674266752667626677266782667926680266812668226683266842668526686266872668826689266902669126692266932669426695266962669726698266992670026701267022670326704267052670626707267082670926710267112671226713267142671526716267172671826719267202672126722267232672426725267262672726728267292673026731267322673326734267352673626737267382673926740267412674226743267442674526746267472674826749267502675126752267532675426755267562675726758267592676026761267622676326764267652676626767267682676926770267712677226773267742677526776267772677826779267802678126782267832678426785267862678726788267892679026791267922679326794267952679626797267982679926800268012680226803268042680526806268072680826809268102681126812268132681426815268162681726818268192682026821268222682326824268252682626827268282682926830268312683226833268342683526836268372683826839268402684126842268432684426845268462684726848268492685026851268522685326854268552685626857268582685926860268612686226863268642686526866268672686826869268702687126872268732687426875268762687726878268792688026881268822688326884268852688626887268882688926890268912689226893268942689526896268972689826899269002690126902269032690426905269062690726908269092691026911269122691326914269152691626917269182691926920269212692226923269242692526926269272692826929269302693126932269332693426935269362693726938269392694026941269422694326944269452694626947269482694926950269512695226953269542695526956269572695826959269602696126962269632696426965269662696726968269692697026971269722697326974269752697626977269782697926980269812698226983269842698526986269872698826989269902699126992269932699426995269962699726998269992700027001270022700327004270052700627007270082700927010270112701227013270142701527016270172701827019270202702127022270232702427025270262702727028270292703027031270322703327034270352703627037270382703927040270412704227043270442704527046270472704827049270502705127052270532705427055270562705727058270592706027061270622706327064270652706627067270682706927070270712707227073270742707527076270772707827079270802708127082270832708427085270862708727088270892709027091270922709327094270952709627097270982709927100271012710227103271042710527106271072710827109271102711127112271132711427115271162711727118271192712027121271222712327124271252712627127271282712927130271312713227133271342713527136271372713827139271402714127142271432714427145271462714727148271492715027151271522715327154271552715627157271582715927160271612716227163271642716527166271672716827169271702717127172271732717427175271762717727178271792718027181271822718327184271852718627187271882718927190271912719227193271942719527196271972719827199272002720127202272032720427205272062720727208272092721027211272122721327214272152721627217272182721927220272212722227223272242722527226272272722827229272302723127232272332723427235272362723727238272392724027241272422724327244272452724627247272482724927250272512725227253272542725527256272572725827259272602726127262272632726427265272662726727268272692727027271272722727327274272752727627277272782727927280272812728227283272842728527286272872728827289272902729127292272932729427295272962729727298272992730027301273022730327304273052730627307273082730927310273112731227313273142731527316273172731827319273202732127322273232732427325273262732727328273292733027331273322733327334273352733627337273382733927340273412734227343273442734527346273472734827349273502735127352273532735427355273562735727358273592736027361273622736327364273652736627367273682736927370273712737227373273742737527376273772737827379273802738127382273832738427385273862738727388273892739027391273922739327394273952739627397273982739927400274012740227403274042740527406274072740827409274102741127412274132741427415274162741727418274192742027421274222742327424274252742627427274282742927430274312743227433274342743527436274372743827439274402744127442274432744427445274462744727448274492745027451274522745327454274552745627457274582745927460274612746227463274642746527466274672746827469274702747127472274732747427475274762747727478274792748027481274822748327484274852748627487274882748927490274912749227493274942749527496274972749827499275002750127502275032750427505275062750727508275092751027511275122751327514275152751627517275182751927520275212752227523275242752527526275272752827529275302753127532275332753427535275362753727538275392754027541275422754327544275452754627547275482754927550275512755227553275542755527556275572755827559275602756127562275632756427565275662756727568275692757027571275722757327574275752757627577275782757927580275812758227583275842758527586275872758827589275902759127592275932759427595275962759727598275992760027601276022760327604276052760627607276082760927610276112761227613276142761527616276172761827619276202762127622276232762427625276262762727628276292763027631276322763327634276352763627637276382763927640276412764227643276442764527646276472764827649276502765127652276532765427655276562765727658276592766027661276622766327664276652766627667276682766927670276712767227673276742767527676276772767827679276802768127682276832768427685276862768727688276892769027691276922769327694276952769627697276982769927700277012770227703277042770527706277072770827709277102771127712277132771427715277162771727718277192772027721277222772327724277252772627727277282772927730277312773227733277342773527736277372773827739277402774127742277432774427745277462774727748277492775027751277522775327754277552775627757277582775927760277612776227763277642776527766277672776827769277702777127772277732777427775277762777727778277792778027781277822778327784277852778627787277882778927790277912779227793277942779527796277972779827799278002780127802278032780427805278062780727808278092781027811278122781327814278152781627817278182781927820278212782227823278242782527826278272782827829278302783127832278332783427835278362783727838278392784027841278422784327844278452784627847278482784927850278512785227853278542785527856278572785827859278602786127862278632786427865278662786727868278692787027871278722787327874278752787627877278782787927880278812788227883278842788527886278872788827889278902789127892278932789427895278962789727898278992790027901279022790327904279052790627907279082790927910279112791227913279142791527916279172791827919279202792127922279232792427925279262792727928279292793027931279322793327934279352793627937279382793927940279412794227943279442794527946279472794827949279502795127952279532795427955279562795727958279592796027961279622796327964279652796627967279682796927970279712797227973279742797527976279772797827979279802798127982279832798427985279862798727988279892799027991279922799327994279952799627997279982799928000280012800228003280042800528006280072800828009280102801128012280132801428015280162801728018280192802028021280222802328024280252802628027280282802928030280312803228033280342803528036280372803828039280402804128042280432804428045280462804728048280492805028051280522805328054280552805628057280582805928060280612806228063280642806528066280672806828069280702807128072280732807428075280762807728078280792808028081280822808328084280852808628087280882808928090280912809228093280942809528096280972809828099281002810128102281032810428105281062810728108281092811028111281122811328114281152811628117281182811928120281212812228123281242812528126281272812828129281302813128132281332813428135281362813728138281392814028141281422814328144281452814628147281482814928150281512815228153281542815528156281572815828159281602816128162281632816428165281662816728168281692817028171281722817328174281752817628177281782817928180281812818228183281842818528186281872818828189281902819128192281932819428195281962819728198281992820028201282022820328204282052820628207282082820928210282112821228213282142821528216282172821828219282202822128222282232822428225282262822728228282292823028231282322823328234282352823628237282382823928240282412824228243282442824528246282472824828249282502825128252282532825428255282562825728258282592826028261282622826328264282652826628267282682826928270282712827228273282742827528276282772827828279282802828128282282832828428285282862828728288282892829028291282922829328294282952829628297282982829928300283012830228303283042830528306283072830828309283102831128312283132831428315283162831728318283192832028321283222832328324283252832628327283282832928330283312833228333283342833528336283372833828339283402834128342283432834428345283462834728348283492835028351283522835328354283552835628357283582835928360283612836228363283642836528366283672836828369283702837128372283732837428375283762837728378283792838028381283822838328384283852838628387283882838928390283912839228393283942839528396283972839828399284002840128402284032840428405284062840728408284092841028411284122841328414284152841628417284182841928420284212842228423284242842528426284272842828429284302843128432284332843428435284362843728438284392844028441284422844328444284452844628447284482844928450284512845228453284542845528456284572845828459284602846128462284632846428465284662846728468284692847028471284722847328474284752847628477284782847928480284812848228483284842848528486284872848828489284902849128492284932849428495284962849728498284992850028501285022850328504285052850628507285082850928510285112851228513285142851528516285172851828519285202852128522285232852428525285262852728528285292853028531285322853328534285352853628537285382853928540285412854228543285442854528546285472854828549285502855128552285532855428555285562855728558285592856028561285622856328564285652856628567285682856928570285712857228573285742857528576285772857828579285802858128582285832858428585285862858728588285892859028591285922859328594285952859628597285982859928600286012860228603286042860528606286072860828609286102861128612286132861428615286162861728618286192862028621286222862328624286252862628627286282862928630286312863228633286342863528636286372863828639286402864128642286432864428645286462864728648286492865028651286522865328654286552865628657286582865928660286612866228663286642866528666286672866828669286702867128672286732867428675286762867728678286792868028681286822868328684286852868628687286882868928690286912869228693286942869528696286972869828699287002870128702287032870428705287062870728708287092871028711287122871328714287152871628717287182871928720287212872228723287242872528726287272872828729287302873128732287332873428735287362873728738287392874028741287422874328744287452874628747287482874928750287512875228753287542875528756287572875828759287602876128762287632876428765287662876728768287692877028771287722877328774287752877628777287782877928780287812878228783287842878528786287872878828789287902879128792287932879428795287962879728798287992880028801288022880328804288052880628807288082880928810288112881228813288142881528816288172881828819288202882128822288232882428825288262882728828288292883028831288322883328834288352883628837288382883928840288412884228843288442884528846288472884828849288502885128852288532885428855288562885728858288592886028861288622886328864288652886628867288682886928870288712887228873288742887528876288772887828879288802888128882288832888428885288862888728888288892889028891288922889328894288952889628897288982889928900289012890228903289042890528906289072890828909289102891128912289132891428915289162891728918289192892028921289222892328924289252892628927289282892928930289312893228933289342893528936289372893828939289402894128942289432894428945289462894728948289492895028951289522895328954289552895628957289582895928960289612896228963289642896528966289672896828969289702897128972289732897428975289762897728978289792898028981289822898328984289852898628987289882898928990289912899228993289942899528996289972899828999290002900129002290032900429005290062900729008290092901029011290122901329014290152901629017290182901929020290212902229023290242902529026290272902829029290302903129032290332903429035290362903729038290392904029041290422904329044290452904629047290482904929050290512905229053290542905529056290572905829059290602906129062290632906429065290662906729068290692907029071290722907329074290752907629077290782907929080290812908229083290842908529086290872908829089290902909129092290932909429095290962909729098290992910029101291022910329104291052910629107291082910929110291112911229113291142911529116291172911829119291202912129122291232912429125291262912729128291292913029131291322913329134291352913629137291382913929140291412914229143291442914529146291472914829149291502915129152291532915429155291562915729158291592916029161291622916329164291652916629167291682916929170291712917229173291742917529176291772917829179291802918129182291832918429185291862918729188291892919029191291922919329194291952919629197291982919929200292012920229203292042920529206292072920829209292102921129212292132921429215292162921729218292192922029221292222922329224292252922629227292282922929230292312923229233292342923529236292372923829239292402924129242292432924429245292462924729248292492925029251292522925329254292552925629257292582925929260292612926229263292642926529266292672926829269292702927129272292732927429275292762927729278292792928029281292822928329284292852928629287292882928929290292912929229293292942929529296292972929829299293002930129302293032930429305293062930729308293092931029311293122931329314293152931629317293182931929320293212932229323293242932529326293272932829329293302933129332293332933429335293362933729338293392934029341293422934329344293452934629347293482934929350293512935229353293542935529356293572935829359293602936129362293632936429365293662936729368293692937029371293722937329374293752937629377293782937929380293812938229383293842938529386293872938829389293902939129392293932939429395293962939729398293992940029401294022940329404294052940629407294082940929410294112941229413294142941529416294172941829419294202942129422294232942429425294262942729428294292943029431294322943329434294352943629437294382943929440294412944229443294442944529446294472944829449294502945129452294532945429455294562945729458294592946029461294622946329464294652946629467294682946929470294712947229473294742947529476294772947829479294802948129482294832948429485294862948729488294892949029491294922949329494294952949629497294982949929500295012950229503295042950529506295072950829509295102951129512295132951429515295162951729518295192952029521295222952329524295252952629527295282952929530295312953229533295342953529536295372953829539295402954129542295432954429545295462954729548295492955029551295522955329554295552955629557295582955929560295612956229563295642956529566295672956829569295702957129572295732957429575295762957729578295792958029581295822958329584295852958629587295882958929590295912959229593295942959529596295972959829599296002960129602296032960429605296062960729608296092961029611296122961329614296152961629617296182961929620296212962229623296242962529626296272962829629296302963129632296332963429635296362963729638296392964029641296422964329644296452964629647296482964929650296512965229653296542965529656296572965829659296602966129662296632966429665296662966729668296692967029671296722967329674296752967629677296782967929680296812968229683296842968529686296872968829689296902969129692296932969429695296962969729698296992970029701297022970329704297052970629707297082970929710297112971229713297142971529716297172971829719297202972129722297232972429725297262972729728297292973029731297322973329734297352973629737297382973929740297412974229743297442974529746297472974829749297502975129752297532975429755297562975729758297592976029761297622976329764297652976629767297682976929770297712977229773297742977529776297772977829779297802978129782297832978429785297862978729788297892979029791297922979329794297952979629797297982979929800298012980229803298042980529806298072980829809298102981129812298132981429815298162981729818298192982029821298222982329824298252982629827298282982929830298312983229833298342983529836298372983829839298402984129842298432984429845298462984729848298492985029851298522985329854298552985629857298582985929860298612986229863298642986529866298672986829869298702987129872298732987429875298762987729878298792988029881298822988329884298852988629887298882988929890298912989229893298942989529896298972989829899299002990129902299032990429905299062990729908299092991029911299122991329914299152991629917299182991929920299212992229923299242992529926299272992829929299302993129932299332993429935299362993729938299392994029941299422994329944299452994629947299482994929950299512995229953299542995529956299572995829959299602996129962299632996429965299662996729968299692997029971299722997329974299752997629977299782997929980299812998229983299842998529986299872998829989299902999129992299932999429995299962999729998299993000030001300023000330004300053000630007300083000930010300113001230013300143001530016300173001830019300203002130022300233002430025300263002730028300293003030031300323003330034300353003630037300383003930040300413004230043300443004530046300473004830049300503005130052300533005430055300563005730058300593006030061300623006330064300653006630067300683006930070300713007230073300743007530076300773007830079300803008130082300833008430085300863008730088300893009030091300923009330094300953009630097300983009930100301013010230103301043010530106301073010830109301103011130112301133011430115301163011730118301193012030121301223012330124301253012630127301283012930130301313013230133301343013530136301373013830139301403014130142301433014430145301463014730148301493015030151301523015330154301553015630157301583015930160301613016230163301643016530166301673016830169301703017130172301733017430175301763017730178301793018030181301823018330184301853018630187301883018930190301913019230193301943019530196301973019830199302003020130202302033020430205302063020730208302093021030211302123021330214302153021630217302183021930220302213022230223302243022530226302273022830229302303023130232302333023430235302363023730238302393024030241302423024330244302453024630247302483024930250302513025230253302543025530256302573025830259302603026130262302633026430265302663026730268302693027030271302723027330274302753027630277302783027930280302813028230283302843028530286302873028830289302903029130292302933029430295302963029730298302993030030301303023030330304303053030630307303083030930310303113031230313303143031530316303173031830319303203032130322303233032430325303263032730328303293033030331303323033330334303353033630337303383033930340303413034230343303443034530346303473034830349303503035130352303533035430355303563035730358303593036030361303623036330364303653036630367303683036930370303713037230373303743037530376303773037830379303803038130382303833038430385303863038730388303893039030391303923039330394303953039630397303983039930400304013040230403304043040530406304073040830409304103041130412304133041430415304163041730418304193042030421304223042330424304253042630427304283042930430304313043230433304343043530436304373043830439304403044130442304433044430445304463044730448304493045030451304523045330454304553045630457304583045930460304613046230463304643046530466304673046830469304703047130472304733047430475304763047730478304793048030481304823048330484304853048630487304883048930490304913049230493304943049530496304973049830499305003050130502305033050430505305063050730508305093051030511305123051330514305153051630517305183051930520305213052230523305243052530526305273052830529305303053130532305333053430535305363053730538305393054030541305423054330544305453054630547305483054930550305513055230553305543055530556305573055830559305603056130562305633056430565305663056730568305693057030571305723057330574305753057630577305783057930580305813058230583305843058530586305873058830589305903059130592305933059430595305963059730598305993060030601306023060330604306053060630607306083060930610306113061230613306143061530616306173061830619306203062130622306233062430625306263062730628306293063030631306323063330634306353063630637306383063930640306413064230643306443064530646306473064830649306503065130652306533065430655306563065730658306593066030661306623066330664306653066630667306683066930670306713067230673306743067530676306773067830679306803068130682306833068430685306863068730688306893069030691306923069330694306953069630697306983069930700307013070230703307043070530706307073070830709307103071130712307133071430715307163071730718307193072030721307223072330724307253072630727307283072930730307313073230733307343073530736307373073830739307403074130742307433074430745307463074730748307493075030751307523075330754307553075630757307583075930760307613076230763307643076530766307673076830769307703077130772307733077430775307763077730778307793078030781307823078330784307853078630787307883078930790307913079230793307943079530796307973079830799308003080130802308033080430805308063080730808308093081030811308123081330814308153081630817308183081930820308213082230823308243082530826308273082830829308303083130832308333083430835308363083730838308393084030841308423084330844308453084630847308483084930850308513085230853308543085530856308573085830859308603086130862308633086430865308663086730868308693087030871308723087330874308753087630877308783087930880308813088230883308843088530886308873088830889308903089130892308933089430895308963089730898308993090030901309023090330904309053090630907309083090930910309113091230913309143091530916309173091830919309203092130922309233092430925309263092730928309293093030931309323093330934309353093630937309383093930940309413094230943309443094530946309473094830949309503095130952309533095430955309563095730958309593096030961309623096330964309653096630967309683096930970309713097230973309743097530976309773097830979309803098130982309833098430985309863098730988309893099030991309923099330994309953099630997309983099931000310013100231003310043100531006310073100831009310103101131012310133101431015310163101731018310193102031021310223102331024310253102631027310283102931030310313103231033310343103531036310373103831039310403104131042310433104431045310463104731048310493105031051310523105331054310553105631057310583105931060310613106231063310643106531066310673106831069310703107131072310733107431075310763107731078310793108031081310823108331084310853108631087310883108931090310913109231093310943109531096310973109831099311003110131102311033110431105311063110731108311093111031111311123111331114311153111631117311183111931120311213112231123311243112531126311273112831129311303113131132311333113431135311363113731138311393114031141311423114331144311453114631147311483114931150311513115231153311543115531156311573115831159311603116131162311633116431165311663116731168311693117031171311723117331174311753117631177311783117931180311813118231183311843118531186311873118831189311903119131192311933119431195311963119731198311993120031201312023120331204312053120631207312083120931210312113121231213312143121531216312173121831219312203122131222312233122431225312263122731228312293123031231312323123331234312353123631237312383123931240312413124231243312443124531246312473124831249312503125131252312533125431255312563125731258312593126031261312623126331264312653126631267312683126931270312713127231273312743127531276312773127831279312803128131282312833128431285312863128731288312893129031291312923129331294312953129631297312983129931300313013130231303313043130531306313073130831309313103131131312313133131431315313163131731318313193132031321313223132331324313253132631327313283132931330313313133231333313343133531336313373133831339313403134131342313433134431345313463134731348313493135031351313523135331354313553135631357313583135931360313613136231363313643136531366313673136831369313703137131372313733137431375313763137731378313793138031381313823138331384313853138631387313883138931390313913139231393313943139531396313973139831399314003140131402314033140431405314063140731408314093141031411314123141331414314153141631417314183141931420314213142231423314243142531426314273142831429314303143131432314333143431435314363143731438314393144031441314423144331444314453144631447314483144931450314513145231453314543145531456314573145831459314603146131462314633146431465314663146731468314693147031471314723147331474314753147631477314783147931480314813148231483314843148531486314873148831489314903149131492314933149431495314963149731498314993150031501315023150331504315053150631507315083150931510315113151231513315143151531516315173151831519315203152131522315233152431525315263152731528315293153031531315323153331534315353153631537315383153931540315413154231543315443154531546315473154831549315503155131552315533155431555315563155731558315593156031561315623156331564315653156631567315683156931570315713157231573315743157531576315773157831579315803158131582315833158431585315863158731588315893159031591315923159331594315953159631597315983159931600316013160231603316043160531606316073160831609316103161131612316133161431615316163161731618316193162031621316223162331624316253162631627316283162931630316313163231633316343163531636316373163831639316403164131642316433164431645316463164731648316493165031651316523165331654316553165631657316583165931660316613166231663316643166531666316673166831669316703167131672316733167431675316763167731678316793168031681316823168331684316853168631687316883168931690316913169231693316943169531696316973169831699317003170131702317033170431705317063170731708317093171031711317123171331714317153171631717317183171931720317213172231723317243172531726317273172831729317303173131732317333173431735317363173731738317393174031741317423174331744317453174631747317483174931750317513175231753317543175531756317573175831759317603176131762317633176431765317663176731768317693177031771317723177331774317753177631777317783177931780317813178231783317843178531786317873178831789317903179131792317933179431795317963179731798317993180031801318023180331804318053180631807318083180931810318113181231813318143181531816318173181831819318203182131822318233182431825318263182731828318293183031831318323183331834318353183631837318383183931840318413184231843318443184531846318473184831849318503185131852318533185431855318563185731858318593186031861318623186331864318653186631867318683186931870318713187231873318743187531876318773187831879318803188131882318833188431885318863188731888318893189031891318923189331894318953189631897318983189931900319013190231903319043190531906319073190831909319103191131912319133191431915319163191731918319193192031921319223192331924319253192631927319283192931930319313193231933319343193531936319373193831939319403194131942319433194431945319463194731948319493195031951319523195331954319553195631957319583195931960319613196231963319643196531966319673196831969319703197131972319733197431975319763197731978319793198031981319823198331984319853198631987319883198931990319913199231993319943199531996319973199831999320003200132002320033200432005320063200732008320093201032011320123201332014320153201632017320183201932020320213202232023320243202532026320273202832029320303203132032320333203432035320363203732038320393204032041320423204332044320453204632047320483204932050320513205232053320543205532056320573205832059320603206132062320633206432065320663206732068320693207032071320723207332074320753207632077320783207932080320813208232083320843208532086320873208832089320903209132092320933209432095320963209732098320993210032101321023210332104321053210632107321083210932110321113211232113321143211532116321173211832119321203212132122321233212432125321263212732128321293213032131321323213332134321353213632137321383213932140321413214232143321443214532146321473214832149321503215132152321533215432155321563215732158321593216032161321623216332164321653216632167321683216932170321713217232173321743217532176321773217832179321803218132182321833218432185321863218732188321893219032191321923219332194321953219632197321983219932200322013220232203322043220532206322073220832209322103221132212322133221432215322163221732218322193222032221322223222332224322253222632227322283222932230322313223232233322343223532236322373223832239322403224132242322433224432245322463224732248322493225032251322523225332254322553225632257322583225932260322613226232263322643226532266322673226832269322703227132272322733227432275322763227732278322793228032281322823228332284322853228632287322883228932290322913229232293322943229532296322973229832299323003230132302323033230432305323063230732308323093231032311323123231332314323153231632317323183231932320323213232232323323243232532326323273232832329323303233132332323333233432335323363233732338323393234032341323423234332344323453234632347323483234932350323513235232353323543235532356323573235832359323603236132362323633236432365323663236732368323693237032371323723237332374323753237632377323783237932380323813238232383323843238532386323873238832389323903239132392323933239432395323963239732398323993240032401324023240332404324053240632407324083240932410324113241232413324143241532416324173241832419324203242132422324233242432425324263242732428324293243032431324323243332434324353243632437324383243932440324413244232443324443244532446324473244832449324503245132452324533245432455324563245732458324593246032461324623246332464324653246632467324683246932470324713247232473324743247532476324773247832479324803248132482324833248432485324863248732488324893249032491324923249332494324953249632497324983249932500325013250232503325043250532506325073250832509325103251132512325133251432515325163251732518325193252032521325223252332524325253252632527325283252932530325313253232533325343253532536325373253832539325403254132542325433254432545325463254732548325493255032551325523255332554325553255632557325583255932560325613256232563325643256532566325673256832569325703257132572325733257432575325763257732578325793258032581325823258332584325853258632587325883258932590325913259232593325943259532596325973259832599326003260132602326033260432605326063260732608326093261032611326123261332614326153261632617326183261932620326213262232623326243262532626326273262832629326303263132632326333263432635326363263732638326393264032641326423264332644326453264632647326483264932650326513265232653326543265532656326573265832659326603266132662326633266432665326663266732668326693267032671326723267332674326753267632677326783267932680326813268232683326843268532686326873268832689326903269132692326933269432695326963269732698326993270032701327023270332704327053270632707327083270932710327113271232713327143271532716327173271832719327203272132722327233272432725327263272732728327293273032731327323273332734327353273632737327383273932740327413274232743327443274532746327473274832749327503275132752327533275432755327563275732758327593276032761327623276332764327653276632767327683276932770327713277232773327743277532776327773277832779327803278132782327833278432785327863278732788327893279032791327923279332794327953279632797327983279932800328013280232803328043280532806328073280832809328103281132812328133281432815328163281732818328193282032821328223282332824328253282632827328283282932830328313283232833328343283532836328373283832839328403284132842328433284432845328463284732848328493285032851328523285332854328553285632857328583285932860328613286232863328643286532866328673286832869328703287132872328733287432875328763287732878328793288032881328823288332884328853288632887328883288932890328913289232893328943289532896328973289832899329003290132902329033290432905329063290732908329093291032911329123291332914329153291632917329183291932920329213292232923329243292532926329273292832929329303293132932329333293432935329363293732938329393294032941329423294332944329453294632947329483294932950329513295232953329543295532956329573295832959329603296132962329633296432965329663296732968329693297032971329723297332974329753297632977329783297932980329813298232983329843298532986329873298832989329903299132992329933299432995329963299732998329993300033001330023300333004330053300633007330083300933010330113301233013330143301533016330173301833019330203302133022330233302433025330263302733028330293303033031330323303333034330353303633037330383303933040330413304233043330443304533046330473304833049330503305133052330533305433055330563305733058330593306033061330623306333064330653306633067330683306933070330713307233073330743307533076330773307833079330803308133082330833308433085330863308733088330893309033091330923309333094330953309633097330983309933100331013310233103331043310533106331073310833109331103311133112331133311433115331163311733118331193312033121331223312333124331253312633127331283312933130331313313233133331343313533136331373313833139331403314133142331433314433145331463314733148331493315033151331523315333154331553315633157331583315933160331613316233163331643316533166331673316833169331703317133172331733317433175331763317733178331793318033181331823318333184331853318633187331883318933190331913319233193331943319533196331973319833199332003320133202332033320433205332063320733208332093321033211332123321333214332153321633217332183321933220332213322233223332243322533226332273322833229332303323133232332333323433235332363323733238332393324033241332423324333244332453324633247332483324933250332513325233253332543325533256332573325833259332603326133262332633326433265332663326733268332693327033271332723327333274332753327633277332783327933280332813328233283332843328533286332873328833289332903329133292332933329433295332963329733298332993330033301333023330333304333053330633307333083330933310333113331233313333143331533316333173331833319333203332133322333233332433325333263332733328333293333033331333323333333334333353333633337333383333933340333413334233343333443334533346333473334833349333503335133352333533335433355333563335733358333593336033361333623336333364333653336633367333683336933370333713337233373333743337533376333773337833379333803338133382333833338433385333863338733388333893339033391333923339333394333953339633397333983339933400334013340233403334043340533406334073340833409334103341133412334133341433415334163341733418334193342033421334223342333424334253342633427334283342933430334313343233433334343343533436334373343833439334403344133442334433344433445334463344733448334493345033451334523345333454334553345633457334583345933460334613346233463334643346533466334673346833469334703347133472334733347433475334763347733478334793348033481334823348333484334853348633487334883348933490334913349233493334943349533496334973349833499335003350133502335033350433505335063350733508335093351033511335123351333514335153351633517335183351933520335213352233523335243352533526335273352833529335303353133532335333353433535335363353733538335393354033541335423354333544335453354633547335483354933550335513355233553335543355533556335573355833559335603356133562335633356433565335663356733568335693357033571335723357333574335753357633577335783357933580335813358233583335843358533586335873358833589335903359133592335933359433595335963359733598335993360033601336023360333604336053360633607336083360933610336113361233613336143361533616336173361833619336203362133622336233362433625336263362733628336293363033631336323363333634336353363633637336383363933640336413364233643336443364533646336473364833649336503365133652336533365433655336563365733658336593366033661336623366333664336653366633667336683366933670336713367233673336743367533676336773367833679336803368133682336833368433685336863368733688336893369033691336923369333694336953369633697336983369933700337013370233703337043370533706337073370833709337103371133712337133371433715337163371733718337193372033721337223372333724337253372633727337283372933730337313373233733337343373533736337373373833739337403374133742337433374433745337463374733748337493375033751337523375333754337553375633757337583375933760337613376233763337643376533766337673376833769337703377133772337733377433775337763377733778337793378033781337823378333784337853378633787337883378933790337913379233793337943379533796337973379833799338003380133802338033380433805338063380733808338093381033811338123381333814338153381633817338183381933820338213382233823338243382533826338273382833829338303383133832338333383433835338363383733838338393384033841338423384333844338453384633847338483384933850338513385233853338543385533856338573385833859338603386133862338633386433865338663386733868338693387033871338723387333874338753387633877338783387933880338813388233883338843388533886338873388833889338903389133892338933389433895338963389733898338993390033901339023390333904339053390633907339083390933910339113391233913339143391533916339173391833919339203392133922339233392433925339263392733928339293393033931339323393333934339353393633937339383393933940339413394233943339443394533946339473394833949339503395133952339533395433955339563395733958339593396033961339623396333964339653396633967339683396933970339713397233973339743397533976339773397833979339803398133982339833398433985339863398733988339893399033991339923399333994339953399633997339983399934000340013400234003340043400534006340073400834009340103401134012340133401434015340163401734018340193402034021340223402334024340253402634027340283402934030340313403234033340343403534036340373403834039340403404134042340433404434045340463404734048340493405034051340523405334054340553405634057340583405934060340613406234063340643406534066340673406834069340703407134072340733407434075340763407734078340793408034081340823408334084340853408634087340883408934090340913409234093340943409534096340973409834099341003410134102341033410434105341063410734108341093411034111341123411334114341153411634117341183411934120341213412234123341243412534126341273412834129341303413134132341333413434135341363413734138341393414034141341423414334144341453414634147341483414934150341513415234153341543415534156341573415834159341603416134162341633416434165341663416734168341693417034171341723417334174341753417634177341783417934180341813418234183341843418534186341873418834189341903419134192341933419434195341963419734198341993420034201342023420334204342053420634207342083420934210342113421234213342143421534216342173421834219342203422134222342233422434225342263422734228342293423034231342323423334234342353423634237342383423934240342413424234243342443424534246342473424834249342503425134252342533425434255342563425734258342593426034261342623426334264342653426634267342683426934270342713427234273342743427534276342773427834279342803428134282342833428434285342863428734288342893429034291342923429334294342953429634297342983429934300343013430234303343043430534306343073430834309343103431134312343133431434315343163431734318343193432034321343223432334324343253432634327343283432934330343313433234333343343433534336343373433834339343403434134342343433434434345343463434734348343493435034351343523435334354343553435634357343583435934360343613436234363343643436534366343673436834369343703437134372343733437434375343763437734378343793438034381343823438334384343853438634387343883438934390343913439234393343943439534396343973439834399344003440134402344033440434405344063440734408344093441034411344123441334414344153441634417344183441934420344213442234423344243442534426344273442834429344303443134432344333443434435344363443734438344393444034441344423444334444344453444634447344483444934450344513445234453344543445534456344573445834459344603446134462344633446434465344663446734468344693447034471344723447334474344753447634477344783447934480344813448234483344843448534486344873448834489344903449134492344933449434495344963449734498344993450034501345023450334504345053450634507345083450934510345113451234513345143451534516345173451834519345203452134522345233452434525345263452734528345293453034531345323453334534345353453634537345383453934540345413454234543345443454534546345473454834549345503455134552345533455434555345563455734558345593456034561345623456334564345653456634567345683456934570345713457234573345743457534576345773457834579345803458134582345833458434585345863458734588345893459034591345923459334594345953459634597345983459934600346013460234603346043460534606346073460834609346103461134612346133461434615346163461734618346193462034621346223462334624346253462634627346283462934630346313463234633346343463534636346373463834639346403464134642346433464434645346463464734648346493465034651346523465334654346553465634657346583465934660346613466234663346643466534666346673466834669346703467134672346733467434675346763467734678346793468034681346823468334684346853468634687346883468934690346913469234693346943469534696346973469834699347003470134702347033470434705347063470734708347093471034711347123471334714347153471634717347183471934720347213472234723347243472534726347273472834729347303473134732347333473434735347363473734738347393474034741347423474334744347453474634747347483474934750347513475234753347543475534756347573475834759347603476134762347633476434765347663476734768347693477034771347723477334774347753477634777347783477934780347813478234783347843478534786347873478834789347903479134792347933479434795347963479734798347993480034801348023480334804348053480634807348083480934810348113481234813348143481534816348173481834819348203482134822348233482434825348263482734828348293483034831348323483334834348353483634837348383483934840348413484234843348443484534846348473484834849348503485134852348533485434855348563485734858348593486034861348623486334864348653486634867348683486934870348713487234873348743487534876348773487834879348803488134882348833488434885348863488734888348893489034891348923489334894348953489634897348983489934900349013490234903349043490534906349073490834909349103491134912349133491434915349163491734918349193492034921349223492334924349253492634927349283492934930349313493234933349343493534936349373493834939349403494134942349433494434945349463494734948349493495034951349523495334954349553495634957349583495934960349613496234963349643496534966349673496834969349703497134972349733497434975349763497734978349793498034981349823498334984349853498634987349883498934990349913499234993349943499534996349973499834999350003500135002350033500435005350063500735008350093501035011350123501335014350153501635017350183501935020350213502235023350243502535026350273502835029350303503135032350333503435035350363503735038350393504035041350423504335044350453504635047350483504935050350513505235053350543505535056350573505835059350603506135062350633506435065350663506735068350693507035071350723507335074350753507635077350783507935080350813508235083350843508535086350873508835089350903509135092350933509435095350963509735098350993510035101351023510335104351053510635107351083510935110351113511235113351143511535116351173511835119351203512135122351233512435125351263512735128351293513035131351323513335134351353513635137351383513935140351413514235143351443514535146351473514835149351503515135152351533515435155351563515735158351593516035161351623516335164351653516635167351683516935170351713517235173351743517535176351773517835179351803518135182351833518435185351863518735188351893519035191351923519335194351953519635197351983519935200352013520235203352043520535206352073520835209352103521135212352133521435215352163521735218352193522035221352223522335224352253522635227352283522935230352313523235233352343523535236352373523835239352403524135242352433524435245352463524735248352493525035251352523525335254352553525635257352583525935260352613526235263352643526535266352673526835269352703527135272352733527435275352763527735278352793528035281352823528335284352853528635287352883528935290352913529235293352943529535296352973529835299353003530135302353033530435305353063530735308353093531035311353123531335314353153531635317353183531935320353213532235323353243532535326353273532835329353303533135332353333533435335353363533735338353393534035341353423534335344353453534635347353483534935350353513535235353353543535535356353573535835359353603536135362353633536435365353663536735368353693537035371353723537335374353753537635377353783537935380353813538235383353843538535386353873538835389353903539135392353933539435395353963539735398353993540035401354023540335404354053540635407354083540935410354113541235413354143541535416354173541835419354203542135422354233542435425354263542735428354293543035431354323543335434354353543635437354383543935440354413544235443354443544535446354473544835449354503545135452354533545435455354563545735458354593546035461354623546335464354653546635467354683546935470354713547235473354743547535476354773547835479354803548135482354833548435485354863548735488354893549035491354923549335494354953549635497354983549935500355013550235503355043550535506355073550835509355103551135512355133551435515355163551735518355193552035521355223552335524355253552635527355283552935530355313553235533355343553535536355373553835539355403554135542355433554435545355463554735548355493555035551355523555335554355553555635557355583555935560355613556235563355643556535566355673556835569355703557135572355733557435575355763557735578355793558035581355823558335584355853558635587355883558935590355913559235593355943559535596355973559835599356003560135602356033560435605356063560735608356093561035611356123561335614356153561635617356183561935620356213562235623356243562535626356273562835629356303563135632356333563435635356363563735638356393564035641356423564335644356453564635647356483564935650356513565235653356543565535656356573565835659356603566135662356633566435665356663566735668356693567035671356723567335674356753567635677356783567935680356813568235683356843568535686356873568835689356903569135692356933569435695356963569735698356993570035701357023570335704357053570635707357083570935710357113571235713357143571535716357173571835719357203572135722357233572435725357263572735728357293573035731357323573335734357353573635737357383573935740357413574235743357443574535746357473574835749357503575135752357533575435755357563575735758357593576035761357623576335764357653576635767357683576935770357713577235773357743577535776357773577835779357803578135782357833578435785357863578735788357893579035791357923579335794357953579635797357983579935800358013580235803358043580535806358073580835809358103581135812358133581435815358163581735818358193582035821358223582335824358253582635827358283582935830358313583235833358343583535836358373583835839358403584135842358433584435845358463584735848358493585035851358523585335854358553585635857358583585935860358613586235863358643586535866358673586835869358703587135872358733587435875358763587735878358793588035881358823588335884358853588635887358883588935890358913589235893358943589535896358973589835899359003590135902359033590435905359063590735908359093591035911359123591335914359153591635917359183591935920359213592235923359243592535926359273592835929359303593135932359333593435935359363593735938359393594035941359423594335944359453594635947359483594935950359513595235953359543595535956359573595835959359603596135962359633596435965359663596735968359693597035971359723597335974359753597635977359783597935980359813598235983359843598535986359873598835989359903599135992359933599435995359963599735998359993600036001360023600336004360053600636007360083600936010360113601236013360143601536016360173601836019360203602136022360233602436025360263602736028360293603036031360323603336034360353603636037360383603936040360413604236043360443604536046360473604836049360503605136052360533605436055360563605736058360593606036061360623606336064360653606636067360683606936070360713607236073360743607536076360773607836079360803608136082360833608436085360863608736088360893609036091360923609336094360953609636097360983609936100361013610236103361043610536106361073610836109361103611136112361133611436115361163611736118361193612036121361223612336124361253612636127361283612936130361313613236133361343613536136361373613836139361403614136142361433614436145361463614736148361493615036151361523615336154361553615636157361583615936160361613616236163361643616536166361673616836169361703617136172361733617436175361763617736178361793618036181361823618336184361853618636187361883618936190361913619236193361943619536196361973619836199362003620136202362033620436205362063620736208362093621036211362123621336214362153621636217362183621936220362213622236223362243622536226362273622836229362303623136232362333623436235362363623736238362393624036241362423624336244362453624636247362483624936250362513625236253362543625536256362573625836259362603626136262362633626436265362663626736268362693627036271362723627336274362753627636277362783627936280362813628236283362843628536286362873628836289362903629136292362933629436295362963629736298362993630036301363023630336304363053630636307363083630936310363113631236313363143631536316363173631836319363203632136322363233632436325363263632736328363293633036331363323633336334363353633636337363383633936340363413634236343363443634536346363473634836349363503635136352363533635436355363563635736358363593636036361363623636336364363653636636367363683636936370363713637236373363743637536376363773637836379363803638136382363833638436385363863638736388363893639036391363923639336394363953639636397363983639936400364013640236403364043640536406364073640836409364103641136412364133641436415364163641736418364193642036421364223642336424364253642636427364283642936430364313643236433364343643536436364373643836439364403644136442364433644436445364463644736448364493645036451364523645336454364553645636457364583645936460364613646236463364643646536466364673646836469364703647136472364733647436475364763647736478364793648036481364823648336484364853648636487364883648936490364913649236493364943649536496364973649836499365003650136502365033650436505365063650736508365093651036511365123651336514365153651636517365183651936520365213652236523365243652536526365273652836529365303653136532365333653436535365363653736538365393654036541365423654336544365453654636547365483654936550365513655236553365543655536556365573655836559365603656136562365633656436565365663656736568365693657036571365723657336574365753657636577365783657936580365813658236583365843658536586365873658836589365903659136592365933659436595365963659736598365993660036601366023660336604366053660636607366083660936610366113661236613366143661536616366173661836619366203662136622366233662436625366263662736628366293663036631366323663336634366353663636637366383663936640366413664236643366443664536646366473664836649366503665136652366533665436655366563665736658366593666036661366623666336664366653666636667366683666936670366713667236673366743667536676366773667836679366803668136682366833668436685366863668736688366893669036691366923669336694366953669636697366983669936700367013670236703367043670536706367073670836709367103671136712367133671436715367163671736718367193672036721367223672336724367253672636727367283672936730367313673236733367343673536736367373673836739367403674136742367433674436745367463674736748367493675036751367523675336754367553675636757367583675936760367613676236763367643676536766367673676836769367703677136772367733677436775367763677736778367793678036781367823678336784367853678636787367883678936790367913679236793367943679536796367973679836799368003680136802368033680436805368063680736808368093681036811368123681336814368153681636817368183681936820368213682236823368243682536826368273682836829368303683136832368333683436835368363683736838368393684036841368423684336844368453684636847368483684936850368513685236853368543685536856368573685836859368603686136862368633686436865368663686736868368693687036871368723687336874368753687636877368783687936880368813688236883368843688536886368873688836889368903689136892368933689436895368963689736898368993690036901369023690336904369053690636907369083690936910369113691236913369143691536916369173691836919369203692136922369233692436925369263692736928369293693036931369323693336934369353693636937369383693936940369413694236943369443694536946369473694836949369503695136952369533695436955369563695736958369593696036961369623696336964369653696636967369683696936970369713697236973369743697536976369773697836979369803698136982369833698436985369863698736988369893699036991369923699336994369953699636997369983699937000370013700237003370043700537006370073700837009370103701137012370133701437015370163701737018370193702037021370223702337024370253702637027370283702937030370313703237033370343703537036370373703837039370403704137042370433704437045370463704737048370493705037051370523705337054370553705637057370583705937060370613706237063370643706537066370673706837069370703707137072370733707437075370763707737078370793708037081370823708337084370853708637087370883708937090370913709237093370943709537096370973709837099371003710137102371033710437105371063710737108371093711037111371123711337114371153711637117371183711937120371213712237123371243712537126371273712837129371303713137132371333713437135371363713737138371393714037141371423714337144371453714637147371483714937150371513715237153371543715537156371573715837159371603716137162371633716437165371663716737168371693717037171371723717337174371753717637177371783717937180371813718237183371843718537186371873718837189371903719137192371933719437195371963719737198371993720037201372023720337204372053720637207372083720937210372113721237213372143721537216372173721837219372203722137222372233722437225372263722737228372293723037231372323723337234372353723637237372383723937240372413724237243372443724537246372473724837249372503725137252372533725437255372563725737258372593726037261372623726337264372653726637267372683726937270372713727237273372743727537276372773727837279372803728137282372833728437285372863728737288372893729037291372923729337294372953729637297372983729937300373013730237303373043730537306373073730837309373103731137312373133731437315373163731737318373193732037321373223732337324373253732637327373283732937330373313733237333373343733537336373373733837339373403734137342373433734437345373463734737348373493735037351373523735337354373553735637357373583735937360373613736237363373643736537366373673736837369373703737137372373733737437375373763737737378373793738037381373823738337384373853738637387373883738937390373913739237393373943739537396373973739837399374003740137402374033740437405374063740737408374093741037411374123741337414374153741637417374183741937420374213742237423374243742537426374273742837429374303743137432374333743437435374363743737438374393744037441374423744337444374453744637447374483744937450374513745237453374543745537456374573745837459374603746137462374633746437465374663746737468374693747037471374723747337474374753747637477374783747937480374813748237483374843748537486374873748837489374903749137492374933749437495374963749737498374993750037501375023750337504375053750637507375083750937510375113751237513375143751537516375173751837519375203752137522375233752437525375263752737528375293753037531375323753337534375353753637537375383753937540375413754237543375443754537546375473754837549375503755137552375533755437555375563755737558375593756037561375623756337564375653756637567375683756937570375713757237573375743757537576375773757837579375803758137582375833758437585375863758737588375893759037591375923759337594375953759637597375983759937600376013760237603376043760537606376073760837609376103761137612376133761437615376163761737618376193762037621376223762337624376253762637627376283762937630376313763237633376343763537636376373763837639376403764137642376433764437645376463764737648376493765037651376523765337654376553765637657376583765937660376613766237663376643766537666376673766837669376703767137672376733767437675376763767737678376793768037681376823768337684376853768637687376883768937690376913769237693376943769537696376973769837699377003770137702377033770437705377063770737708377093771037711377123771337714377153771637717377183771937720377213772237723377243772537726377273772837729377303773137732377333773437735377363773737738377393774037741377423774337744377453774637747377483774937750377513775237753377543775537756377573775837759377603776137762377633776437765377663776737768377693777037771377723777337774377753777637777377783777937780377813778237783377843778537786377873778837789377903779137792377933779437795377963779737798377993780037801378023780337804378053780637807378083780937810378113781237813378143781537816378173781837819378203782137822378233782437825378263782737828378293783037831378323783337834378353783637837378383783937840378413784237843378443784537846378473784837849378503785137852378533785437855378563785737858378593786037861378623786337864378653786637867378683786937870378713787237873378743787537876378773787837879378803788137882378833788437885378863788737888378893789037891378923789337894378953789637897378983789937900379013790237903379043790537906379073790837909379103791137912379133791437915379163791737918379193792037921379223792337924379253792637927379283792937930379313793237933379343793537936379373793837939379403794137942379433794437945379463794737948379493795037951379523795337954379553795637957379583795937960379613796237963379643796537966379673796837969379703797137972379733797437975379763797737978379793798037981379823798337984379853798637987379883798937990379913799237993379943799537996379973799837999380003800138002380033800438005380063800738008380093801038011380123801338014380153801638017380183801938020380213802238023380243802538026380273802838029380303803138032380333803438035380363803738038380393804038041380423804338044380453804638047380483804938050380513805238053380543805538056380573805838059380603806138062380633806438065380663806738068380693807038071380723807338074380753807638077380783807938080380813808238083380843808538086380873808838089380903809138092380933809438095380963809738098380993810038101381023810338104381053810638107381083810938110381113811238113381143811538116381173811838119381203812138122381233812438125381263812738128381293813038131381323813338134381353813638137381383813938140381413814238143381443814538146381473814838149381503815138152381533815438155381563815738158381593816038161381623816338164381653816638167381683816938170381713817238173381743817538176381773817838179381803818138182381833818438185381863818738188381893819038191381923819338194381953819638197381983819938200382013820238203382043820538206382073820838209382103821138212382133821438215382163821738218382193822038221382223822338224382253822638227382283822938230382313823238233382343823538236382373823838239382403824138242382433824438245382463824738248382493825038251382523825338254382553825638257382583825938260382613826238263382643826538266382673826838269382703827138272382733827438275382763827738278382793828038281382823828338284382853828638287382883828938290382913829238293382943829538296382973829838299383003830138302383033830438305383063830738308383093831038311383123831338314383153831638317383183831938320383213832238323383243832538326383273832838329383303833138332383333833438335383363833738338383393834038341383423834338344383453834638347383483834938350383513835238353383543835538356383573835838359383603836138362383633836438365383663836738368383693837038371383723837338374383753837638377383783837938380383813838238383383843838538386383873838838389383903839138392383933839438395383963839738398383993840038401384023840338404384053840638407384083840938410384113841238413384143841538416384173841838419384203842138422384233842438425384263842738428384293843038431384323843338434384353843638437384383843938440384413844238443384443844538446384473844838449384503845138452384533845438455384563845738458384593846038461384623846338464384653846638467384683846938470384713847238473384743847538476384773847838479384803848138482384833848438485384863848738488384893849038491384923849338494384953849638497384983849938500385013850238503385043850538506385073850838509385103851138512385133851438515385163851738518385193852038521385223852338524385253852638527385283852938530385313853238533385343853538536385373853838539385403854138542385433854438545385463854738548385493855038551385523855338554385553855638557385583855938560385613856238563385643856538566385673856838569385703857138572385733857438575385763857738578385793858038581385823858338584385853858638587385883858938590385913859238593385943859538596385973859838599386003860138602386033860438605386063860738608386093861038611386123861338614386153861638617386183861938620386213862238623386243862538626386273862838629386303863138632386333863438635386363863738638386393864038641386423864338644386453864638647386483864938650386513865238653386543865538656386573865838659386603866138662386633866438665386663866738668386693867038671386723867338674386753867638677386783867938680386813868238683386843868538686386873868838689386903869138692386933869438695386963869738698386993870038701387023870338704387053870638707387083870938710387113871238713387143871538716387173871838719387203872138722387233872438725387263872738728387293873038731387323873338734387353873638737387383873938740387413874238743387443874538746387473874838749387503875138752387533875438755387563875738758387593876038761387623876338764387653876638767387683876938770387713877238773387743877538776387773877838779387803878138782387833878438785387863878738788387893879038791387923879338794387953879638797387983879938800388013880238803388043880538806388073880838809388103881138812388133881438815388163881738818388193882038821388223882338824388253882638827388283882938830388313883238833388343883538836388373883838839388403884138842388433884438845388463884738848388493885038851388523885338854388553885638857388583885938860388613886238863388643886538866388673886838869388703887138872388733887438875388763887738878388793888038881388823888338884388853888638887388883888938890388913889238893388943889538896388973889838899389003890138902389033890438905389063890738908389093891038911389123891338914389153891638917389183891938920389213892238923389243892538926389273892838929389303893138932389333893438935389363893738938389393894038941389423894338944389453894638947389483894938950389513895238953389543895538956389573895838959389603896138962389633896438965389663896738968389693897038971389723897338974389753897638977389783897938980389813898238983389843898538986389873898838989389903899138992389933899438995389963899738998389993900039001390023900339004390053900639007390083900939010390113901239013390143901539016390173901839019390203902139022390233902439025390263902739028390293903039031390323903339034390353903639037390383903939040390413904239043390443904539046390473904839049390503905139052390533905439055390563905739058390593906039061390623906339064390653906639067390683906939070390713907239073390743907539076390773907839079390803908139082390833908439085390863908739088390893909039091390923909339094390953909639097390983909939100391013910239103391043910539106391073910839109391103911139112391133911439115391163911739118391193912039121391223912339124391253912639127391283912939130391313913239133391343913539136391373913839139391403914139142391433914439145391463914739148391493915039151391523915339154391553915639157391583915939160391613916239163391643916539166391673916839169391703917139172391733917439175391763917739178391793918039181391823918339184391853918639187391883918939190391913919239193391943919539196391973919839199392003920139202392033920439205392063920739208392093921039211392123921339214392153921639217392183921939220392213922239223392243922539226392273922839229392303923139232392333923439235392363923739238392393924039241392423924339244392453924639247392483924939250392513925239253392543925539256392573925839259392603926139262392633926439265392663926739268392693927039271392723927339274392753927639277392783927939280392813928239283392843928539286392873928839289392903929139292392933929439295392963929739298392993930039301393023930339304393053930639307393083930939310393113931239313393143931539316393173931839319393203932139322393233932439325393263932739328393293933039331393323933339334393353933639337393383933939340393413934239343393443934539346393473934839349393503935139352393533935439355393563935739358393593936039361393623936339364393653936639367393683936939370393713937239373393743937539376393773937839379393803938139382393833938439385393863938739388393893939039391393923939339394393953939639397393983939939400394013940239403394043940539406394073940839409394103941139412394133941439415394163941739418394193942039421394223942339424394253942639427394283942939430394313943239433394343943539436394373943839439394403944139442394433944439445394463944739448394493945039451394523945339454394553945639457394583945939460394613946239463394643946539466394673946839469394703947139472394733947439475394763947739478394793948039481394823948339484394853948639487394883948939490394913949239493394943949539496394973949839499395003950139502395033950439505395063950739508395093951039511395123951339514395153951639517395183951939520395213952239523395243952539526395273952839529395303953139532395333953439535395363953739538395393954039541395423954339544395453954639547395483954939550395513955239553395543955539556395573955839559395603956139562395633956439565395663956739568395693957039571395723957339574395753957639577395783957939580395813958239583395843958539586395873958839589395903959139592395933959439595395963959739598395993960039601396023960339604396053960639607396083960939610396113961239613396143961539616396173961839619396203962139622396233962439625396263962739628396293963039631396323963339634396353963639637396383963939640396413964239643396443964539646396473964839649396503965139652396533965439655396563965739658396593966039661396623966339664396653966639667396683966939670396713967239673396743967539676396773967839679396803968139682396833968439685396863968739688396893969039691396923969339694396953969639697396983969939700397013970239703397043970539706397073970839709397103971139712397133971439715397163971739718397193972039721397223972339724397253972639727397283972939730397313973239733397343973539736397373973839739397403974139742397433974439745397463974739748397493975039751397523975339754397553975639757397583975939760397613976239763397643976539766397673976839769397703977139772397733977439775397763977739778397793978039781397823978339784397853978639787397883978939790397913979239793397943979539796397973979839799398003980139802398033980439805398063980739808398093981039811398123981339814398153981639817398183981939820398213982239823398243982539826398273982839829398303983139832398333983439835398363983739838398393984039841398423984339844398453984639847398483984939850398513985239853398543985539856398573985839859398603986139862398633986439865398663986739868398693987039871398723987339874398753987639877398783987939880398813988239883398843988539886398873988839889398903989139892398933989439895398963989739898398993990039901399023990339904399053990639907399083990939910399113991239913399143991539916399173991839919399203992139922399233992439925399263992739928399293993039931399323993339934399353993639937399383993939940399413994239943399443994539946399473994839949399503995139952399533995439955399563995739958399593996039961399623996339964399653996639967399683996939970399713997239973399743997539976399773997839979399803998139982399833998439985399863998739988399893999039991399923999339994399953999639997399983999940000400014000240003400044000540006400074000840009400104001140012400134001440015400164001740018400194002040021400224002340024400254002640027400284002940030400314003240033400344003540036400374003840039400404004140042400434004440045400464004740048400494005040051400524005340054400554005640057400584005940060400614006240063400644006540066400674006840069400704007140072400734007440075400764007740078400794008040081400824008340084400854008640087400884008940090400914009240093400944009540096400974009840099401004010140102401034010440105401064010740108401094011040111401124011340114401154011640117401184011940120401214012240123401244012540126401274012840129401304013140132401334013440135401364013740138401394014040141401424014340144401454014640147401484014940150401514015240153401544015540156401574015840159401604016140162401634016440165401664016740168401694017040171401724017340174401754017640177401784017940180401814018240183401844018540186401874018840189401904019140192401934019440195401964019740198401994020040201402024020340204402054020640207402084020940210402114021240213402144021540216402174021840219402204022140222402234022440225402264022740228402294023040231402324023340234402354023640237402384023940240402414024240243402444024540246402474024840249402504025140252402534025440255402564025740258402594026040261402624026340264402654026640267402684026940270402714027240273402744027540276402774027840279402804028140282402834028440285402864028740288402894029040291402924029340294402954029640297402984029940300403014030240303403044030540306403074030840309403104031140312403134031440315403164031740318403194032040321403224032340324403254032640327403284032940330403314033240333403344033540336403374033840339403404034140342403434034440345403464034740348403494035040351403524035340354403554035640357403584035940360403614036240363403644036540366403674036840369403704037140372403734037440375403764037740378403794038040381403824038340384403854038640387403884038940390403914039240393403944039540396403974039840399404004040140402404034040440405404064040740408404094041040411404124041340414404154041640417404184041940420404214042240423404244042540426404274042840429404304043140432404334043440435404364043740438404394044040441404424044340444404454044640447404484044940450404514045240453404544045540456404574045840459404604046140462404634046440465404664046740468404694047040471404724047340474404754047640477404784047940480404814048240483404844048540486404874048840489404904049140492404934049440495404964049740498404994050040501405024050340504405054050640507405084050940510405114051240513405144051540516405174051840519405204052140522405234052440525405264052740528405294053040531405324053340534405354053640537405384053940540405414054240543405444054540546405474054840549405504055140552405534055440555405564055740558405594056040561405624056340564405654056640567405684056940570405714057240573405744057540576405774057840579405804058140582405834058440585405864058740588405894059040591405924059340594405954059640597405984059940600406014060240603406044060540606406074060840609406104061140612406134061440615406164061740618406194062040621406224062340624406254062640627406284062940630406314063240633406344063540636406374063840639406404064140642406434064440645406464064740648406494065040651406524065340654406554065640657406584065940660406614066240663406644066540666406674066840669406704067140672406734067440675406764067740678406794068040681406824068340684406854068640687406884068940690406914069240693406944069540696406974069840699407004070140702407034070440705407064070740708407094071040711407124071340714407154071640717407184071940720407214072240723407244072540726407274072840729407304073140732407334073440735407364073740738407394074040741407424074340744407454074640747407484074940750407514075240753407544075540756407574075840759407604076140762407634076440765407664076740768407694077040771407724077340774407754077640777407784077940780407814078240783407844078540786407874078840789407904079140792407934079440795407964079740798407994080040801408024080340804408054080640807408084080940810408114081240813408144081540816408174081840819408204082140822408234082440825408264082740828408294083040831408324083340834408354083640837408384083940840408414084240843408444084540846408474084840849408504085140852408534085440855408564085740858408594086040861408624086340864408654086640867408684086940870408714087240873408744087540876408774087840879408804088140882408834088440885408864088740888408894089040891408924089340894408954089640897408984089940900409014090240903409044090540906409074090840909409104091140912409134091440915409164091740918409194092040921409224092340924409254092640927409284092940930409314093240933409344093540936409374093840939409404094140942409434094440945409464094740948409494095040951409524095340954409554095640957409584095940960409614096240963409644096540966409674096840969409704097140972409734097440975409764097740978409794098040981409824098340984409854098640987409884098940990409914099240993409944099540996409974099840999410004100141002410034100441005410064100741008410094101041011410124101341014410154101641017410184101941020410214102241023410244102541026410274102841029410304103141032410334103441035410364103741038410394104041041410424104341044410454104641047410484104941050410514105241053410544105541056410574105841059410604106141062410634106441065410664106741068410694107041071410724107341074410754107641077410784107941080410814108241083410844108541086410874108841089410904109141092410934109441095410964109741098410994110041101411024110341104411054110641107411084110941110411114111241113411144111541116411174111841119411204112141122411234112441125411264112741128411294113041131411324113341134411354113641137411384113941140411414114241143411444114541146411474114841149411504115141152411534115441155411564115741158411594116041161411624116341164411654116641167411684116941170411714117241173411744117541176411774117841179411804118141182411834118441185411864118741188411894119041191411924119341194411954119641197411984119941200412014120241203412044120541206412074120841209412104121141212412134121441215412164121741218412194122041221412224122341224412254122641227412284122941230412314123241233412344123541236412374123841239412404124141242412434124441245412464124741248412494125041251412524125341254412554125641257412584125941260412614126241263412644126541266412674126841269412704127141272412734127441275412764127741278412794128041281412824128341284412854128641287412884128941290412914129241293412944129541296412974129841299413004130141302413034130441305413064130741308413094131041311413124131341314413154131641317413184131941320413214132241323413244132541326413274132841329413304133141332413334133441335413364133741338413394134041341413424134341344413454134641347413484134941350413514135241353413544135541356413574135841359413604136141362413634136441365413664136741368413694137041371413724137341374413754137641377413784137941380413814138241383413844138541386413874138841389413904139141392413934139441395413964139741398413994140041401414024140341404414054140641407414084140941410414114141241413414144141541416414174141841419414204142141422414234142441425414264142741428414294143041431414324143341434414354143641437414384143941440414414144241443414444144541446414474144841449414504145141452414534145441455414564145741458414594146041461414624146341464414654146641467414684146941470414714147241473414744147541476414774147841479414804148141482414834148441485414864148741488414894149041491414924149341494414954149641497414984149941500415014150241503415044150541506415074150841509415104151141512415134151441515415164151741518415194152041521415224152341524415254152641527415284152941530415314153241533415344153541536415374153841539415404154141542415434154441545415464154741548415494155041551415524155341554415554155641557415584155941560415614156241563415644156541566415674156841569415704157141572415734157441575415764157741578415794158041581415824158341584415854158641587415884158941590415914159241593415944159541596415974159841599416004160141602416034160441605416064160741608416094161041611416124161341614416154161641617416184161941620416214162241623416244162541626416274162841629416304163141632416334163441635416364163741638416394164041641416424164341644416454164641647416484164941650416514165241653416544165541656416574165841659416604166141662416634166441665416664166741668416694167041671416724167341674416754167641677416784167941680416814168241683416844168541686416874168841689416904169141692416934169441695416964169741698416994170041701417024170341704417054170641707417084170941710417114171241713417144171541716417174171841719417204172141722417234172441725417264172741728417294173041731417324173341734417354173641737417384173941740417414174241743417444174541746417474174841749417504175141752417534175441755417564175741758417594176041761417624176341764417654176641767417684176941770417714177241773417744177541776417774177841779417804178141782417834178441785417864178741788417894179041791417924179341794417954179641797417984179941800418014180241803418044180541806418074180841809418104181141812418134181441815418164181741818418194182041821418224182341824418254182641827418284182941830418314183241833418344183541836418374183841839418404184141842418434184441845418464184741848418494185041851418524185341854418554185641857418584185941860418614186241863418644186541866418674186841869418704187141872418734187441875418764187741878418794188041881418824188341884418854188641887418884188941890418914189241893418944189541896418974189841899419004190141902419034190441905419064190741908419094191041911419124191341914419154191641917419184191941920419214192241923419244192541926419274192841929419304193141932419334193441935419364193741938419394194041941419424194341944419454194641947419484194941950419514195241953419544195541956419574195841959419604196141962419634196441965419664196741968419694197041971419724197341974419754197641977419784197941980419814198241983419844198541986419874198841989419904199141992419934199441995419964199741998419994200042001420024200342004420054200642007420084200942010420114201242013420144201542016420174201842019420204202142022420234202442025420264202742028420294203042031420324203342034420354203642037420384203942040420414204242043420444204542046420474204842049420504205142052420534205442055420564205742058420594206042061420624206342064420654206642067420684206942070420714207242073420744207542076420774207842079420804208142082420834208442085420864208742088420894209042091420924209342094420954209642097420984209942100421014210242103421044210542106421074210842109421104211142112421134211442115421164211742118421194212042121421224212342124421254212642127421284212942130421314213242133421344213542136421374213842139421404214142142421434214442145421464214742148421494215042151421524215342154421554215642157421584215942160421614216242163421644216542166421674216842169421704217142172421734217442175421764217742178421794218042181421824218342184421854218642187421884218942190421914219242193421944219542196421974219842199422004220142202422034220442205422064220742208422094221042211422124221342214422154221642217422184221942220422214222242223422244222542226422274222842229422304223142232422334223442235422364223742238422394224042241422424224342244422454224642247422484224942250422514225242253422544225542256422574225842259422604226142262422634226442265422664226742268422694227042271422724227342274422754227642277422784227942280422814228242283422844228542286422874228842289422904229142292422934229442295422964229742298422994230042301423024230342304423054230642307423084230942310423114231242313423144231542316423174231842319423204232142322423234232442325423264232742328423294233042331423324233342334423354233642337423384233942340423414234242343423444234542346423474234842349423504235142352423534235442355423564235742358423594236042361423624236342364423654236642367423684236942370423714237242373423744237542376423774237842379423804238142382423834238442385423864238742388423894239042391423924239342394423954239642397423984239942400424014240242403424044240542406424074240842409424104241142412424134241442415424164241742418424194242042421424224242342424424254242642427424284242942430424314243242433424344243542436424374243842439424404244142442424434244442445424464244742448424494245042451424524245342454424554245642457424584245942460424614246242463424644246542466424674246842469424704247142472424734247442475424764247742478424794248042481424824248342484424854248642487424884248942490424914249242493424944249542496424974249842499425004250142502425034250442505425064250742508425094251042511425124251342514425154251642517425184251942520425214252242523425244252542526425274252842529425304253142532425334253442535425364253742538425394254042541425424254342544425454254642547425484254942550425514255242553425544255542556425574255842559425604256142562425634256442565425664256742568425694257042571425724257342574425754257642577425784257942580425814258242583425844258542586425874258842589425904259142592425934259442595425964259742598425994260042601426024260342604426054260642607426084260942610426114261242613426144261542616426174261842619426204262142622426234262442625426264262742628426294263042631426324263342634426354263642637426384263942640426414264242643426444264542646426474264842649426504265142652426534265442655426564265742658426594266042661426624266342664426654266642667426684266942670426714267242673426744267542676426774267842679426804268142682426834268442685426864268742688426894269042691426924269342694426954269642697426984269942700427014270242703427044270542706427074270842709427104271142712427134271442715427164271742718427194272042721427224272342724427254272642727427284272942730427314273242733427344273542736427374273842739427404274142742427434274442745427464274742748427494275042751427524275342754427554275642757427584275942760427614276242763427644276542766427674276842769427704277142772427734277442775427764277742778427794278042781427824278342784427854278642787427884278942790427914279242793427944279542796427974279842799428004280142802428034280442805428064280742808428094281042811428124281342814428154281642817428184281942820428214282242823428244282542826428274282842829428304283142832428334283442835428364283742838428394284042841428424284342844428454284642847428484284942850428514285242853428544285542856428574285842859428604286142862428634286442865428664286742868428694287042871428724287342874428754287642877428784287942880428814288242883428844288542886428874288842889428904289142892428934289442895428964289742898428994290042901429024290342904429054290642907429084290942910429114291242913429144291542916429174291842919429204292142922429234292442925429264292742928429294293042931429324293342934429354293642937429384293942940429414294242943429444294542946429474294842949429504295142952429534295442955429564295742958429594296042961429624296342964429654296642967429684296942970429714297242973429744297542976429774297842979429804298142982429834298442985429864298742988429894299042991429924299342994429954299642997429984299943000430014300243003430044300543006430074300843009430104301143012430134301443015430164301743018430194302043021430224302343024430254302643027430284302943030430314303243033430344303543036430374303843039430404304143042430434304443045430464304743048430494305043051430524305343054430554305643057430584305943060430614306243063430644306543066430674306843069430704307143072430734307443075430764307743078430794308043081430824308343084430854308643087430884308943090430914309243093430944309543096430974309843099431004310143102431034310443105431064310743108431094311043111431124311343114431154311643117431184311943120431214312243123431244312543126431274312843129431304313143132431334313443135431364313743138431394314043141431424314343144431454314643147431484314943150431514315243153431544315543156431574315843159431604316143162431634316443165431664316743168431694317043171431724317343174431754317643177431784317943180431814318243183431844318543186431874318843189431904319143192431934319443195431964319743198431994320043201432024320343204432054320643207432084320943210432114321243213432144321543216432174321843219432204322143222432234322443225432264322743228432294323043231432324323343234432354323643237432384323943240432414324243243432444324543246432474324843249432504325143252432534325443255432564325743258432594326043261432624326343264432654326643267432684326943270432714327243273432744327543276432774327843279432804328143282432834328443285432864328743288432894329043291432924329343294432954329643297432984329943300433014330243303433044330543306433074330843309433104331143312433134331443315433164331743318433194332043321433224332343324433254332643327433284332943330433314333243333433344333543336433374333843339433404334143342433434334443345433464334743348433494335043351433524335343354433554335643357433584335943360433614336243363433644336543366433674336843369433704337143372433734337443375433764337743378433794338043381433824338343384433854338643387433884338943390433914339243393433944339543396433974339843399434004340143402434034340443405434064340743408434094341043411434124341343414434154341643417434184341943420434214342243423434244342543426434274342843429434304343143432434334343443435434364343743438434394344043441434424344343444434454344643447434484344943450434514345243453434544345543456434574345843459434604346143462434634346443465434664346743468434694347043471434724347343474434754347643477434784347943480434814348243483434844348543486434874348843489434904349143492434934349443495434964349743498434994350043501435024350343504435054350643507435084350943510435114351243513435144351543516435174351843519435204352143522435234352443525435264352743528435294353043531435324353343534435354353643537435384353943540435414354243543435444354543546435474354843549435504355143552435534355443555435564355743558435594356043561435624356343564435654356643567435684356943570435714357243573435744357543576435774357843579435804358143582435834358443585435864358743588435894359043591435924359343594435954359643597435984359943600436014360243603436044360543606436074360843609436104361143612436134361443615436164361743618436194362043621436224362343624436254362643627436284362943630436314363243633436344363543636436374363843639436404364143642436434364443645436464364743648436494365043651436524365343654436554365643657436584365943660436614366243663436644366543666436674366843669436704367143672436734367443675436764367743678436794368043681436824368343684436854368643687436884368943690436914369243693436944369543696436974369843699437004370143702437034370443705437064370743708437094371043711437124371343714437154371643717437184371943720437214372243723437244372543726437274372843729437304373143732437334373443735437364373743738437394374043741437424374343744437454374643747437484374943750437514375243753437544375543756437574375843759437604376143762437634376443765437664376743768437694377043771437724377343774437754377643777437784377943780437814378243783437844378543786437874378843789437904379143792437934379443795437964379743798437994380043801438024380343804438054380643807438084380943810438114381243813438144381543816438174381843819438204382143822438234382443825438264382743828438294383043831438324383343834438354383643837438384383943840438414384243843438444384543846438474384843849438504385143852438534385443855438564385743858438594386043861438624386343864438654386643867438684386943870438714387243873438744387543876438774387843879438804388143882438834388443885438864388743888438894389043891438924389343894438954389643897438984389943900439014390243903439044390543906439074390843909439104391143912439134391443915439164391743918439194392043921439224392343924439254392643927439284392943930439314393243933439344393543936439374393843939439404394143942439434394443945439464394743948439494395043951439524395343954439554395643957439584395943960439614396243963439644396543966439674396843969439704397143972439734397443975439764397743978439794398043981439824398343984439854398643987439884398943990439914399243993439944399543996439974399843999440004400144002440034400444005440064400744008440094401044011440124401344014440154401644017440184401944020440214402244023440244402544026440274402844029440304403144032440334403444035440364403744038440394404044041440424404344044440454404644047440484404944050440514405244053440544405544056440574405844059440604406144062440634406444065440664406744068440694407044071440724407344074440754407644077440784407944080440814408244083440844408544086440874408844089440904409144092440934409444095440964409744098440994410044101441024410344104441054410644107441084410944110441114411244113441144411544116441174411844119441204412144122441234412444125441264412744128441294413044131441324413344134441354413644137441384413944140441414414244143441444414544146441474414844149441504415144152441534415444155441564415744158441594416044161441624416344164441654416644167441684416944170441714417244173441744417544176441774417844179441804418144182441834418444185441864418744188441894419044191441924419344194441954419644197441984419944200442014420244203442044420544206442074420844209442104421144212442134421444215442164421744218442194422044221442224422344224442254422644227442284422944230442314423244233442344423544236442374423844239442404424144242442434424444245442464424744248442494425044251442524425344254442554425644257442584425944260442614426244263442644426544266442674426844269442704427144272442734427444275442764427744278442794428044281442824428344284442854428644287442884428944290442914429244293442944429544296442974429844299443004430144302443034430444305443064430744308443094431044311443124431344314443154431644317443184431944320443214432244323443244432544326443274432844329443304433144332443334433444335443364433744338443394434044341443424434344344443454434644347443484434944350443514435244353443544435544356443574435844359443604436144362443634436444365443664436744368443694437044371443724437344374443754437644377443784437944380443814438244383443844438544386443874438844389443904439144392443934439444395443964439744398443994440044401444024440344404444054440644407444084440944410444114441244413444144441544416444174441844419444204442144422444234442444425444264442744428444294443044431444324443344434444354443644437444384443944440444414444244443444444444544446444474444844449444504445144452444534445444455444564445744458444594446044461444624446344464444654446644467444684446944470444714447244473444744447544476444774447844479444804448144482444834448444485444864448744488444894449044491444924449344494444954449644497444984449944500445014450244503445044450544506445074450844509445104451144512445134451444515445164451744518445194452044521445224452344524445254452644527445284452944530445314453244533445344453544536445374453844539445404454144542445434454444545445464454744548445494455044551445524455344554445554455644557445584455944560445614456244563445644456544566445674456844569445704457144572445734457444575445764457744578445794458044581445824458344584445854458644587445884458944590445914459244593445944459544596445974459844599446004460144602446034460444605446064460744608446094461044611446124461344614446154461644617446184461944620446214462244623446244462544626446274462844629446304463144632446334463444635446364463744638446394464044641446424464344644446454464644647446484464944650446514465244653446544465544656446574465844659446604466144662446634466444665446664466744668446694467044671446724467344674446754467644677446784467944680446814468244683446844468544686446874468844689446904469144692446934469444695446964469744698446994470044701447024470344704447054470644707447084470944710447114471244713447144471544716447174471844719447204472144722447234472444725447264472744728447294473044731447324473344734447354473644737447384473944740447414474244743447444474544746447474474844749447504475144752447534475444755447564475744758447594476044761447624476344764447654476644767447684476944770447714477244773447744477544776447774477844779447804478144782447834478444785447864478744788447894479044791447924479344794447954479644797447984479944800448014480244803448044480544806448074480844809448104481144812448134481444815448164481744818448194482044821448224482344824448254482644827448284482944830448314483244833448344483544836448374483844839448404484144842448434484444845448464484744848448494485044851448524485344854448554485644857448584485944860448614486244863448644486544866448674486844869448704487144872448734487444875448764487744878448794488044881448824488344884448854488644887448884488944890448914489244893448944489544896448974489844899449004490144902449034490444905449064490744908449094491044911449124491344914449154491644917449184491944920449214492244923449244492544926449274492844929449304493144932449334493444935449364493744938449394494044941449424494344944449454494644947449484494944950449514495244953449544495544956449574495844959449604496144962449634496444965449664496744968449694497044971449724497344974449754497644977449784497944980449814498244983449844498544986449874498844989449904499144992449934499444995449964499744998449994500045001450024500345004450054500645007450084500945010450114501245013450144501545016450174501845019450204502145022450234502445025450264502745028450294503045031450324503345034450354503645037450384503945040450414504245043450444504545046450474504845049450504505145052450534505445055450564505745058450594506045061450624506345064450654506645067450684506945070450714507245073450744507545076450774507845079450804508145082450834508445085450864508745088450894509045091450924509345094450954509645097450984509945100451014510245103451044510545106451074510845109451104511145112451134511445115451164511745118451194512045121451224512345124451254512645127451284512945130451314513245133451344513545136451374513845139451404514145142451434514445145451464514745148451494515045151451524515345154451554515645157451584515945160451614516245163451644516545166451674516845169451704517145172451734517445175451764517745178451794518045181451824518345184451854518645187451884518945190451914519245193451944519545196451974519845199452004520145202452034520445205452064520745208452094521045211452124521345214452154521645217452184521945220452214522245223452244522545226452274522845229452304523145232452334523445235452364523745238452394524045241452424524345244452454524645247452484524945250452514525245253452544525545256452574525845259452604526145262452634526445265452664526745268452694527045271452724527345274452754527645277452784527945280452814528245283452844528545286452874528845289452904529145292452934529445295452964529745298452994530045301453024530345304453054530645307453084530945310453114531245313453144531545316453174531845319453204532145322453234532445325453264532745328453294533045331453324533345334453354533645337453384533945340453414534245343453444534545346453474534845349453504535145352453534535445355453564535745358453594536045361453624536345364453654536645367453684536945370453714537245373453744537545376453774537845379453804538145382453834538445385453864538745388453894539045391453924539345394453954539645397453984539945400454014540245403454044540545406454074540845409454104541145412454134541445415454164541745418454194542045421454224542345424454254542645427454284542945430454314543245433454344543545436454374543845439454404544145442454434544445445454464544745448454494545045451454524545345454454554545645457454584545945460454614546245463454644546545466454674546845469454704547145472454734547445475454764547745478454794548045481454824548345484454854548645487454884548945490454914549245493454944549545496454974549845499455004550145502455034550445505455064550745508455094551045511455124551345514455154551645517455184551945520455214552245523455244552545526455274552845529455304553145532455334553445535455364553745538455394554045541455424554345544455454554645547455484554945550455514555245553455544555545556455574555845559455604556145562455634556445565455664556745568455694557045571455724557345574455754557645577455784557945580455814558245583455844558545586455874558845589455904559145592455934559445595455964559745598455994560045601456024560345604456054560645607456084560945610456114561245613456144561545616456174561845619456204562145622456234562445625456264562745628456294563045631456324563345634456354563645637456384563945640456414564245643456444564545646456474564845649456504565145652456534565445655456564565745658456594566045661456624566345664456654566645667456684566945670456714567245673456744567545676456774567845679456804568145682456834568445685456864568745688456894569045691456924569345694456954569645697456984569945700457014570245703457044570545706457074570845709457104571145712457134571445715457164571745718457194572045721457224572345724457254572645727457284572945730457314573245733457344573545736457374573845739457404574145742457434574445745457464574745748457494575045751457524575345754457554575645757457584575945760457614576245763457644576545766457674576845769457704577145772457734577445775457764577745778457794578045781457824578345784457854578645787457884578945790457914579245793457944579545796457974579845799458004580145802458034580445805458064580745808458094581045811458124581345814458154581645817458184581945820458214582245823458244582545826458274582845829458304583145832458334583445835458364583745838458394584045841458424584345844458454584645847458484584945850458514585245853458544585545856458574585845859458604586145862458634586445865458664586745868458694587045871458724587345874458754587645877458784587945880458814588245883458844588545886458874588845889458904589145892458934589445895458964589745898458994590045901459024590345904459054590645907459084590945910459114591245913459144591545916459174591845919459204592145922459234592445925459264592745928459294593045931459324593345934459354593645937459384593945940459414594245943459444594545946459474594845949459504595145952459534595445955459564595745958459594596045961459624596345964459654596645967459684596945970459714597245973459744597545976459774597845979459804598145982459834598445985459864598745988459894599045991459924599345994459954599645997459984599946000460014600246003460044600546006460074600846009460104601146012460134601446015460164601746018460194602046021460224602346024460254602646027460284602946030460314603246033460344603546036460374603846039460404604146042460434604446045460464604746048460494605046051460524605346054460554605646057460584605946060460614606246063460644606546066460674606846069460704607146072460734607446075460764607746078460794608046081460824608346084460854608646087460884608946090460914609246093460944609546096460974609846099461004610146102461034610446105461064610746108461094611046111461124611346114461154611646117461184611946120461214612246123461244612546126461274612846129461304613146132461334613446135461364613746138461394614046141461424614346144461454614646147461484614946150461514615246153461544615546156461574615846159461604616146162461634616446165461664616746168461694617046171461724617346174461754617646177461784617946180461814618246183461844618546186461874618846189461904619146192461934619446195461964619746198461994620046201462024620346204462054620646207462084620946210462114621246213462144621546216462174621846219462204622146222462234622446225462264622746228462294623046231462324623346234462354623646237462384623946240462414624246243462444624546246462474624846249462504625146252462534625446255462564625746258462594626046261462624626346264462654626646267462684626946270462714627246273462744627546276462774627846279462804628146282462834628446285462864628746288462894629046291462924629346294462954629646297462984629946300463014630246303463044630546306463074630846309463104631146312463134631446315463164631746318463194632046321463224632346324463254632646327463284632946330463314633246333463344633546336463374633846339463404634146342463434634446345463464634746348463494635046351463524635346354463554635646357463584635946360463614636246363463644636546366463674636846369463704637146372463734637446375463764637746378463794638046381463824638346384463854638646387463884638946390463914639246393463944639546396463974639846399464004640146402464034640446405464064640746408464094641046411464124641346414464154641646417464184641946420464214642246423464244642546426464274642846429464304643146432464334643446435464364643746438464394644046441464424644346444464454644646447464484644946450464514645246453464544645546456464574645846459464604646146462464634646446465464664646746468464694647046471464724647346474464754647646477464784647946480464814648246483464844648546486464874648846489464904649146492464934649446495464964649746498464994650046501465024650346504465054650646507465084650946510465114651246513465144651546516465174651846519465204652146522465234652446525465264652746528465294653046531465324653346534465354653646537465384653946540465414654246543465444654546546465474654846549465504655146552465534655446555465564655746558465594656046561465624656346564465654656646567465684656946570465714657246573465744657546576465774657846579465804658146582465834658446585465864658746588465894659046591465924659346594465954659646597465984659946600466014660246603466044660546606466074660846609466104661146612466134661446615466164661746618466194662046621466224662346624466254662646627466284662946630466314663246633466344663546636466374663846639466404664146642466434664446645466464664746648466494665046651466524665346654466554665646657466584665946660466614666246663466644666546666466674666846669466704667146672466734667446675466764667746678466794668046681466824668346684466854668646687466884668946690466914669246693466944669546696466974669846699467004670146702467034670446705467064670746708467094671046711467124671346714467154671646717467184671946720467214672246723467244672546726467274672846729467304673146732467334673446735467364673746738467394674046741467424674346744467454674646747467484674946750467514675246753467544675546756467574675846759467604676146762467634676446765467664676746768467694677046771467724677346774467754677646777467784677946780467814678246783467844678546786467874678846789467904679146792467934679446795467964679746798467994680046801468024680346804468054680646807468084680946810468114681246813468144681546816468174681846819468204682146822468234682446825468264682746828468294683046831468324683346834468354683646837468384683946840468414684246843468444684546846468474684846849468504685146852468534685446855468564685746858468594686046861468624686346864468654686646867468684686946870468714687246873468744687546876468774687846879468804688146882468834688446885468864688746888468894689046891468924689346894468954689646897468984689946900469014690246903469044690546906469074690846909469104691146912469134691446915469164691746918469194692046921469224692346924469254692646927469284692946930469314693246933469344693546936469374693846939469404694146942469434694446945469464694746948469494695046951469524695346954469554695646957469584695946960469614696246963469644696546966469674696846969469704697146972469734697446975469764697746978469794698046981469824698346984469854698646987469884698946990469914699246993469944699546996469974699846999470004700147002470034700447005470064700747008470094701047011470124701347014470154701647017470184701947020470214702247023470244702547026470274702847029470304703147032470334703447035470364703747038470394704047041470424704347044470454704647047470484704947050470514705247053470544705547056470574705847059470604706147062470634706447065470664706747068470694707047071470724707347074470754707647077470784707947080470814708247083470844708547086470874708847089470904709147092470934709447095470964709747098470994710047101471024710347104471054710647107471084710947110471114711247113471144711547116471174711847119471204712147122471234712447125471264712747128471294713047131471324713347134471354713647137471384713947140471414714247143471444714547146471474714847149471504715147152471534715447155471564715747158471594716047161471624716347164471654716647167471684716947170471714717247173471744717547176471774717847179471804718147182471834718447185471864718747188471894719047191471924719347194471954719647197471984719947200472014720247203472044720547206472074720847209472104721147212472134721447215472164721747218472194722047221472224722347224472254722647227472284722947230472314723247233472344723547236472374723847239472404724147242472434724447245472464724747248472494725047251472524725347254472554725647257472584725947260472614726247263472644726547266472674726847269472704727147272472734727447275472764727747278472794728047281472824728347284472854728647287472884728947290472914729247293472944729547296472974729847299473004730147302473034730447305473064730747308473094731047311473124731347314473154731647317473184731947320473214732247323473244732547326473274732847329473304733147332473334733447335473364733747338473394734047341473424734347344473454734647347473484734947350473514735247353473544735547356473574735847359473604736147362473634736447365473664736747368473694737047371473724737347374473754737647377473784737947380473814738247383473844738547386473874738847389473904739147392473934739447395473964739747398473994740047401474024740347404474054740647407474084740947410474114741247413474144741547416474174741847419474204742147422474234742447425474264742747428474294743047431474324743347434474354743647437474384743947440474414744247443474444744547446474474744847449474504745147452474534745447455474564745747458474594746047461474624746347464474654746647467474684746947470474714747247473474744747547476474774747847479474804748147482474834748447485474864748747488474894749047491474924749347494474954749647497474984749947500475014750247503475044750547506475074750847509475104751147512475134751447515475164751747518475194752047521475224752347524475254752647527475284752947530475314753247533475344753547536475374753847539475404754147542475434754447545475464754747548475494755047551475524755347554475554755647557475584755947560475614756247563475644756547566475674756847569475704757147572475734757447575475764757747578475794758047581475824758347584475854758647587475884758947590475914759247593475944759547596475974759847599476004760147602476034760447605476064760747608476094761047611476124761347614476154761647617476184761947620476214762247623476244762547626476274762847629476304763147632476334763447635476364763747638476394764047641476424764347644476454764647647476484764947650476514765247653476544765547656476574765847659476604766147662476634766447665476664766747668476694767047671476724767347674476754767647677476784767947680476814768247683476844768547686476874768847689476904769147692476934769447695476964769747698476994770047701477024770347704477054770647707477084770947710477114771247713477144771547716477174771847719477204772147722477234772447725477264772747728477294773047731477324773347734477354773647737477384773947740477414774247743477444774547746477474774847749477504775147752477534775447755477564775747758477594776047761477624776347764477654776647767477684776947770477714777247773477744777547776477774777847779477804778147782477834778447785477864778747788477894779047791477924779347794477954779647797477984779947800478014780247803478044780547806478074780847809478104781147812478134781447815478164781747818478194782047821478224782347824478254782647827478284782947830478314783247833478344783547836478374783847839478404784147842478434784447845478464784747848478494785047851478524785347854478554785647857478584785947860478614786247863478644786547866478674786847869478704787147872478734787447875478764787747878478794788047881478824788347884478854788647887478884788947890478914789247893478944789547896478974789847899479004790147902479034790447905479064790747908479094791047911479124791347914479154791647917479184791947920479214792247923479244792547926479274792847929479304793147932479334793447935479364793747938479394794047941479424794347944479454794647947479484794947950479514795247953479544795547956479574795847959479604796147962479634796447965479664796747968479694797047971479724797347974479754797647977479784797947980479814798247983479844798547986479874798847989479904799147992479934799447995479964799747998479994800048001480024800348004480054800648007480084800948010480114801248013480144801548016480174801848019480204802148022480234802448025480264802748028480294803048031480324803348034480354803648037480384803948040480414804248043480444804548046480474804848049480504805148052480534805448055480564805748058480594806048061480624806348064480654806648067480684806948070480714807248073480744807548076480774807848079480804808148082480834808448085480864808748088480894809048091480924809348094480954809648097480984809948100481014810248103481044810548106481074810848109481104811148112481134811448115481164811748118481194812048121481224812348124481254812648127481284812948130481314813248133481344813548136481374813848139481404814148142481434814448145481464814748148481494815048151481524815348154481554815648157481584815948160481614816248163481644816548166481674816848169481704817148172481734817448175481764817748178481794818048181481824818348184481854818648187481884818948190481914819248193481944819548196481974819848199482004820148202482034820448205482064820748208482094821048211482124821348214482154821648217482184821948220482214822248223482244822548226482274822848229482304823148232482334823448235482364823748238482394824048241482424824348244482454824648247482484824948250482514825248253482544825548256482574825848259482604826148262482634826448265482664826748268482694827048271482724827348274482754827648277482784827948280482814828248283482844828548286482874828848289482904829148292482934829448295482964829748298482994830048301483024830348304483054830648307483084830948310483114831248313483144831548316483174831848319483204832148322483234832448325483264832748328483294833048331483324833348334483354833648337483384833948340483414834248343483444834548346483474834848349483504835148352483534835448355483564835748358483594836048361483624836348364483654836648367483684836948370483714837248373483744837548376483774837848379483804838148382483834838448385483864838748388483894839048391483924839348394483954839648397483984839948400484014840248403484044840548406484074840848409484104841148412484134841448415484164841748418484194842048421484224842348424484254842648427484284842948430484314843248433484344843548436484374843848439484404844148442484434844448445484464844748448484494845048451484524845348454484554845648457484584845948460484614846248463484644846548466484674846848469484704847148472484734847448475484764847748478484794848048481484824848348484484854848648487484884848948490484914849248493484944849548496484974849848499485004850148502485034850448505485064850748508485094851048511485124851348514485154851648517485184851948520485214852248523485244852548526485274852848529485304853148532485334853448535485364853748538485394854048541485424854348544485454854648547485484854948550485514855248553485544855548556485574855848559485604856148562485634856448565485664856748568485694857048571485724857348574485754857648577485784857948580485814858248583485844858548586485874858848589485904859148592485934859448595485964859748598485994860048601486024860348604486054860648607486084860948610486114861248613486144861548616486174861848619486204862148622486234862448625486264862748628486294863048631486324863348634486354863648637486384863948640486414864248643486444864548646486474864848649486504865148652486534865448655486564865748658486594866048661486624866348664486654866648667486684866948670486714867248673486744867548676486774867848679486804868148682486834868448685486864868748688486894869048691486924869348694486954869648697486984869948700487014870248703487044870548706487074870848709487104871148712487134871448715487164871748718487194872048721487224872348724487254872648727487284872948730487314873248733487344873548736487374873848739487404874148742487434874448745487464874748748487494875048751487524875348754487554875648757487584875948760487614876248763487644876548766487674876848769487704877148772487734877448775487764877748778487794878048781487824878348784487854878648787487884878948790487914879248793487944879548796487974879848799488004880148802488034880448805488064880748808488094881048811488124881348814488154881648817488184881948820488214882248823488244882548826488274882848829488304883148832488334883448835488364883748838488394884048841488424884348844488454884648847488484884948850488514885248853488544885548856488574885848859488604886148862488634886448865488664886748868488694887048871488724887348874488754887648877488784887948880488814888248883488844888548886488874888848889488904889148892488934889448895488964889748898488994890048901489024890348904489054890648907489084890948910489114891248913489144891548916489174891848919489204892148922489234892448925489264892748928489294893048931489324893348934489354893648937489384893948940489414894248943489444894548946489474894848949489504895148952489534895448955489564895748958489594896048961489624896348964489654896648967489684896948970489714897248973489744897548976489774897848979489804898148982489834898448985489864898748988489894899048991489924899348994489954899648997489984899949000490014900249003490044900549006490074900849009490104901149012490134901449015490164901749018490194902049021490224902349024490254902649027490284902949030490314903249033490344903549036490374903849039490404904149042490434904449045490464904749048490494905049051490524905349054490554905649057490584905949060490614906249063490644906549066490674906849069490704907149072490734907449075490764907749078490794908049081490824908349084490854908649087490884908949090490914909249093490944909549096490974909849099491004910149102491034910449105491064910749108491094911049111491124911349114491154911649117491184911949120491214912249123491244912549126491274912849129491304913149132491334913449135491364913749138491394914049141491424914349144491454914649147491484914949150491514915249153491544915549156491574915849159491604916149162491634916449165491664916749168491694917049171491724917349174491754917649177491784917949180491814918249183491844918549186491874918849189491904919149192491934919449195491964919749198491994920049201492024920349204492054920649207492084920949210492114921249213492144921549216492174921849219492204922149222492234922449225492264922749228492294923049231492324923349234492354923649237492384923949240492414924249243492444924549246492474924849249492504925149252492534925449255492564925749258492594926049261492624926349264492654926649267492684926949270492714927249273492744927549276492774927849279492804928149282492834928449285492864928749288492894929049291492924929349294492954929649297492984929949300493014930249303493044930549306493074930849309493104931149312493134931449315493164931749318493194932049321493224932349324493254932649327493284932949330493314933249333493344933549336493374933849339493404934149342493434934449345493464934749348493494935049351493524935349354493554935649357493584935949360493614936249363493644936549366493674936849369493704937149372493734937449375493764937749378493794938049381493824938349384493854938649387493884938949390493914939249393493944939549396493974939849399494004940149402494034940449405494064940749408494094941049411494124941349414494154941649417494184941949420494214942249423494244942549426494274942849429494304943149432494334943449435494364943749438494394944049441494424944349444494454944649447494484944949450494514945249453494544945549456494574945849459494604946149462494634946449465494664946749468494694947049471494724947349474494754947649477494784947949480494814948249483494844948549486494874948849489494904949149492494934949449495494964949749498494994950049501495024950349504495054950649507495084950949510495114951249513495144951549516495174951849519495204952149522495234952449525495264952749528495294953049531495324953349534495354953649537495384953949540495414954249543495444954549546495474954849549495504955149552495534955449555495564955749558495594956049561495624956349564495654956649567495684956949570495714957249573495744957549576495774957849579495804958149582495834958449585495864958749588495894959049591495924959349594495954959649597495984959949600496014960249603496044960549606496074960849609496104961149612496134961449615496164961749618496194962049621496224962349624496254962649627496284962949630496314963249633496344963549636496374963849639496404964149642496434964449645496464964749648496494965049651496524965349654496554965649657496584965949660496614966249663496644966549666496674966849669496704967149672496734967449675496764967749678496794968049681496824968349684496854968649687496884968949690496914969249693496944969549696496974969849699497004970149702497034970449705497064970749708497094971049711497124971349714497154971649717497184971949720497214972249723497244972549726497274972849729497304973149732497334973449735497364973749738497394974049741497424974349744497454974649747497484974949750497514975249753497544975549756497574975849759497604976149762497634976449765497664976749768497694977049771497724977349774497754977649777497784977949780497814978249783497844978549786497874978849789497904979149792497934979449795497964979749798497994980049801498024980349804498054980649807498084980949810498114981249813498144981549816498174981849819498204982149822498234982449825498264982749828498294983049831498324983349834498354983649837498384983949840498414984249843498444984549846498474984849849498504985149852498534985449855498564985749858498594986049861498624986349864498654986649867498684986949870498714987249873498744987549876498774987849879498804988149882498834988449885498864988749888498894989049891498924989349894498954989649897498984989949900499014990249903499044990549906499074990849909499104991149912499134991449915499164991749918499194992049921499224992349924499254992649927499284992949930499314993249933499344993549936499374993849939499404994149942499434994449945499464994749948499494995049951499524995349954499554995649957499584995949960499614996249963499644996549966499674996849969499704997149972499734997449975499764997749978499794998049981499824998349984499854998649987499884998949990499914999249993499944999549996499974999849999500005000150002500035000450005500065000750008500095001050011500125001350014500155001650017500185001950020500215002250023500245002550026500275002850029500305003150032500335003450035500365003750038500395004050041500425004350044500455004650047500485004950050500515005250053500545005550056500575005850059500605006150062500635006450065500665006750068500695007050071500725007350074500755007650077500785007950080500815008250083500845008550086500875008850089500905009150092500935009450095500965009750098500995010050101501025010350104501055010650107501085010950110501115011250113501145011550116501175011850119501205012150122501235012450125501265012750128501295013050131501325013350134501355013650137501385013950140501415014250143501445014550146501475014850149501505015150152501535015450155501565015750158501595016050161501625016350164501655016650167501685016950170501715017250173501745017550176501775017850179501805018150182501835018450185501865018750188501895019050191501925019350194501955019650197501985019950200502015020250203502045020550206502075020850209502105021150212502135021450215502165021750218502195022050221502225022350224502255022650227502285022950230502315023250233502345023550236502375023850239502405024150242502435024450245502465024750248502495025050251502525025350254502555025650257502585025950260502615026250263502645026550266502675026850269502705027150272502735027450275502765027750278502795028050281502825028350284502855028650287502885028950290502915029250293502945029550296502975029850299503005030150302503035030450305503065030750308503095031050311503125031350314503155031650317503185031950320503215032250323503245032550326503275032850329503305033150332503335033450335503365033750338503395034050341503425034350344503455034650347503485034950350503515035250353503545035550356503575035850359503605036150362503635036450365503665036750368503695037050371503725037350374503755037650377503785037950380503815038250383503845038550386503875038850389503905039150392503935039450395503965039750398503995040050401504025040350404504055040650407504085040950410504115041250413504145041550416504175041850419504205042150422504235042450425504265042750428504295043050431504325043350434504355043650437504385043950440504415044250443504445044550446504475044850449504505045150452504535045450455504565045750458504595046050461504625046350464504655046650467504685046950470504715047250473504745047550476504775047850479504805048150482504835048450485504865048750488504895049050491504925049350494504955049650497504985049950500505015050250503505045050550506505075050850509505105051150512505135051450515505165051750518505195052050521505225052350524505255052650527505285052950530505315053250533505345053550536505375053850539505405054150542505435054450545505465054750548505495055050551505525055350554505555055650557505585055950560505615056250563505645056550566505675056850569505705057150572505735057450575505765057750578505795058050581505825058350584505855058650587505885058950590505915059250593505945059550596505975059850599506005060150602506035060450605506065060750608506095061050611506125061350614506155061650617506185061950620506215062250623506245062550626506275062850629506305063150632506335063450635506365063750638506395064050641506425064350644506455064650647506485064950650506515065250653506545065550656506575065850659506605066150662506635066450665506665066750668506695067050671506725067350674506755067650677506785067950680506815068250683506845068550686506875068850689506905069150692506935069450695506965069750698506995070050701507025070350704507055070650707507085070950710507115071250713507145071550716507175071850719507205072150722507235072450725507265072750728507295073050731507325073350734507355073650737507385073950740507415074250743507445074550746507475074850749507505075150752507535075450755507565075750758507595076050761507625076350764507655076650767507685076950770507715077250773507745077550776507775077850779507805078150782507835078450785507865078750788507895079050791507925079350794507955079650797507985079950800508015080250803508045080550806508075080850809508105081150812508135081450815508165081750818508195082050821508225082350824508255082650827508285082950830508315083250833508345083550836508375083850839508405084150842508435084450845508465084750848508495085050851508525085350854508555085650857508585085950860508615086250863508645086550866508675086850869508705087150872508735087450875508765087750878508795088050881508825088350884508855088650887508885088950890508915089250893508945089550896508975089850899509005090150902509035090450905509065090750908509095091050911509125091350914509155091650917509185091950920509215092250923509245092550926509275092850929509305093150932509335093450935509365093750938509395094050941509425094350944509455094650947509485094950950509515095250953509545095550956509575095850959509605096150962509635096450965509665096750968509695097050971509725097350974509755097650977509785097950980509815098250983509845098550986509875098850989509905099150992509935099450995509965099750998509995100051001510025100351004510055100651007510085100951010510115101251013510145101551016510175101851019510205102151022510235102451025510265102751028510295103051031510325103351034510355103651037510385103951040510415104251043510445104551046510475104851049510505105151052510535105451055510565105751058510595106051061510625106351064510655106651067510685106951070510715107251073510745107551076510775107851079510805108151082510835108451085510865108751088510895109051091510925109351094510955109651097510985109951100511015110251103511045110551106511075110851109511105111151112511135111451115511165111751118511195112051121511225112351124511255112651127511285112951130511315113251133511345113551136511375113851139511405114151142511435114451145511465114751148511495115051151511525115351154511555115651157511585115951160511615116251163511645116551166511675116851169511705117151172511735117451175511765117751178511795118051181511825118351184511855118651187511885118951190511915119251193511945119551196511975119851199512005120151202512035120451205512065120751208512095121051211512125121351214512155121651217512185121951220512215122251223512245122551226512275122851229512305123151232512335123451235512365123751238512395124051241512425124351244512455124651247512485124951250512515125251253512545125551256512575125851259512605126151262512635126451265512665126751268512695127051271512725127351274512755127651277512785127951280512815128251283512845128551286512875128851289512905129151292512935129451295512965129751298512995130051301513025130351304513055130651307513085130951310513115131251313513145131551316513175131851319513205132151322513235132451325513265132751328513295133051331513325133351334513355133651337513385133951340513415134251343513445134551346513475134851349513505135151352513535135451355513565135751358513595136051361513625136351364513655136651367513685136951370513715137251373513745137551376513775137851379513805138151382513835138451385513865138751388513895139051391513925139351394513955139651397513985139951400514015140251403514045140551406514075140851409514105141151412514135141451415514165141751418514195142051421514225142351424514255142651427514285142951430514315143251433514345143551436514375143851439514405144151442514435144451445514465144751448514495145051451514525145351454514555145651457514585145951460514615146251463514645146551466514675146851469514705147151472514735147451475514765147751478514795148051481514825148351484514855148651487514885148951490514915149251493514945149551496514975149851499515005150151502515035150451505515065150751508515095151051511515125151351514515155151651517515185151951520515215152251523515245152551526515275152851529515305153151532515335153451535515365153751538515395154051541515425154351544515455154651547515485154951550515515155251553515545155551556515575155851559515605156151562515635156451565515665156751568515695157051571515725157351574515755157651577515785157951580515815158251583515845158551586515875158851589515905159151592515935159451595515965159751598515995160051601516025160351604516055160651607516085160951610516115161251613516145161551616516175161851619516205162151622516235162451625516265162751628516295163051631516325163351634516355163651637516385163951640516415164251643516445164551646516475164851649516505165151652516535165451655516565165751658516595166051661516625166351664516655166651667516685166951670516715167251673516745167551676516775167851679516805168151682516835168451685516865168751688516895169051691516925169351694516955169651697516985169951700517015170251703517045170551706517075170851709517105171151712517135171451715517165171751718517195172051721517225172351724517255172651727517285172951730517315173251733517345173551736517375173851739517405174151742517435174451745517465174751748517495175051751517525175351754517555175651757517585175951760517615176251763517645176551766517675176851769517705177151772517735177451775517765177751778517795178051781517825178351784517855178651787517885178951790517915179251793517945179551796517975179851799518005180151802518035180451805518065180751808518095181051811518125181351814518155181651817518185181951820518215182251823518245182551826518275182851829518305183151832518335183451835518365183751838518395184051841518425184351844518455184651847518485184951850518515185251853518545185551856518575185851859518605186151862518635186451865518665186751868518695187051871518725187351874518755187651877518785187951880518815188251883518845188551886518875188851889518905189151892518935189451895518965189751898518995190051901519025190351904519055190651907519085190951910519115191251913519145191551916519175191851919519205192151922519235192451925519265192751928519295193051931519325193351934519355193651937519385193951940519415194251943519445194551946519475194851949519505195151952519535195451955519565195751958519595196051961519625196351964519655196651967519685196951970519715197251973519745197551976519775197851979519805198151982519835198451985519865198751988519895199051991519925199351994519955199651997519985199952000520015200252003520045200552006520075200852009520105201152012520135201452015520165201752018520195202052021520225202352024520255202652027520285202952030520315203252033520345203552036520375203852039520405204152042520435204452045520465204752048520495205052051520525205352054520555205652057520585205952060520615206252063520645206552066520675206852069520705207152072520735207452075520765207752078520795208052081520825208352084520855208652087520885208952090520915209252093520945209552096520975209852099521005210152102521035210452105521065210752108521095211052111521125211352114521155211652117521185211952120521215212252123521245212552126521275212852129521305213152132521335213452135521365213752138521395214052141521425214352144521455214652147521485214952150521515215252153521545215552156521575215852159521605216152162521635216452165521665216752168521695217052171521725217352174521755217652177521785217952180521815218252183521845218552186521875218852189521905219152192521935219452195521965219752198521995220052201522025220352204522055220652207522085220952210522115221252213522145221552216522175221852219522205222152222522235222452225522265222752228522295223052231522325223352234522355223652237522385223952240522415224252243522445224552246522475224852249522505225152252522535225452255522565225752258522595226052261522625226352264522655226652267522685226952270522715227252273522745227552276522775227852279522805228152282522835228452285522865228752288522895229052291522925229352294522955229652297522985229952300523015230252303523045230552306523075230852309523105231152312523135231452315523165231752318523195232052321523225232352324523255232652327523285232952330523315233252333523345233552336523375233852339523405234152342523435234452345523465234752348523495235052351523525235352354523555235652357523585235952360523615236252363523645236552366523675236852369523705237152372523735237452375523765237752378523795238052381523825238352384523855238652387523885238952390523915239252393523945239552396523975239852399524005240152402524035240452405524065240752408524095241052411524125241352414524155241652417524185241952420524215242252423524245242552426524275242852429524305243152432524335243452435524365243752438524395244052441524425244352444524455244652447524485244952450524515245252453524545245552456524575245852459524605246152462524635246452465524665246752468524695247052471524725247352474524755247652477524785247952480524815248252483524845248552486524875248852489524905249152492524935249452495524965249752498524995250052501525025250352504525055250652507525085250952510525115251252513525145251552516525175251852519525205252152522525235252452525525265252752528525295253052531525325253352534525355253652537525385253952540525415254252543525445254552546525475254852549525505255152552525535255452555525565255752558525595256052561525625256352564525655256652567525685256952570525715257252573525745257552576525775257852579525805258152582525835258452585525865258752588525895259052591525925259352594525955259652597525985259952600526015260252603526045260552606526075260852609526105261152612526135261452615526165261752618526195262052621526225262352624526255262652627526285262952630526315263252633526345263552636526375263852639526405264152642526435264452645526465264752648526495265052651526525265352654526555265652657526585265952660526615266252663526645266552666526675266852669526705267152672526735267452675526765267752678526795268052681526825268352684526855268652687526885268952690526915269252693526945269552696526975269852699527005270152702527035270452705527065270752708527095271052711527125271352714527155271652717527185271952720527215272252723527245272552726527275272852729527305273152732527335273452735527365273752738527395274052741527425274352744527455274652747527485274952750527515275252753527545275552756527575275852759527605276152762527635276452765527665276752768527695277052771527725277352774527755277652777527785277952780527815278252783527845278552786527875278852789527905279152792527935279452795527965279752798527995280052801528025280352804528055280652807528085280952810528115281252813528145281552816528175281852819528205282152822528235282452825528265282752828528295283052831528325283352834528355283652837528385283952840528415284252843528445284552846528475284852849528505285152852528535285452855528565285752858528595286052861528625286352864528655286652867528685286952870528715287252873528745287552876528775287852879528805288152882528835288452885528865288752888528895289052891528925289352894528955289652897528985289952900529015290252903529045290552906529075290852909529105291152912529135291452915529165291752918529195292052921529225292352924529255292652927529285292952930529315293252933529345293552936529375293852939529405294152942529435294452945529465294752948529495295052951529525295352954529555295652957529585295952960529615296252963529645296552966529675296852969529705297152972529735297452975529765297752978529795298052981529825298352984529855298652987529885298952990529915299252993529945299552996529975299852999530005300153002530035300453005530065300753008530095301053011530125301353014530155301653017530185301953020530215302253023530245302553026530275302853029530305303153032530335303453035530365303753038530395304053041530425304353044530455304653047530485304953050530515305253053530545305553056530575305853059530605306153062530635306453065530665306753068530695307053071530725307353074530755307653077530785307953080530815308253083530845308553086530875308853089530905309153092530935309453095530965309753098530995310053101531025310353104531055310653107531085310953110531115311253113531145311553116531175311853119531205312153122531235312453125531265312753128531295313053131531325313353134531355313653137531385313953140531415314253143531445314553146531475314853149531505315153152531535315453155531565315753158531595316053161531625316353164531655316653167531685316953170531715317253173531745317553176531775317853179531805318153182531835318453185531865318753188531895319053191531925319353194531955319653197531985319953200532015320253203532045320553206532075320853209532105321153212532135321453215532165321753218532195322053221532225322353224532255322653227532285322953230532315323253233532345323553236532375323853239532405324153242532435324453245532465324753248532495325053251532525325353254532555325653257532585325953260532615326253263532645326553266532675326853269532705327153272532735327453275532765327753278532795328053281532825328353284532855328653287532885328953290532915329253293532945329553296532975329853299533005330153302533035330453305533065330753308533095331053311533125331353314533155331653317533185331953320533215332253323533245332553326533275332853329533305333153332533335333453335533365333753338533395334053341533425334353344533455334653347533485334953350533515335253353533545335553356533575335853359533605336153362533635336453365533665336753368533695337053371533725337353374533755337653377533785337953380533815338253383533845338553386533875338853389533905339153392533935339453395533965339753398533995340053401534025340353404534055340653407534085340953410534115341253413534145341553416534175341853419534205342153422534235342453425534265342753428534295343053431534325343353434534355343653437534385343953440534415344253443534445344553446534475344853449534505345153452534535345453455534565345753458534595346053461534625346353464534655346653467534685346953470534715347253473534745347553476534775347853479534805348153482534835348453485534865348753488534895349053491534925349353494534955349653497534985349953500535015350253503535045350553506535075350853509535105351153512535135351453515535165351753518535195352053521535225352353524535255352653527535285352953530535315353253533535345353553536535375353853539535405354153542535435354453545535465354753548535495355053551535525355353554535555355653557535585355953560535615356253563535645356553566535675356853569535705357153572535735357453575535765357753578535795358053581535825358353584535855358653587535885358953590535915359253593535945359553596535975359853599536005360153602536035360453605536065360753608536095361053611536125361353614536155361653617536185361953620536215362253623536245362553626536275362853629536305363153632536335363453635536365363753638536395364053641536425364353644536455364653647536485364953650536515365253653536545365553656536575365853659536605366153662536635366453665536665366753668536695367053671536725367353674536755367653677536785367953680536815368253683536845368553686536875368853689536905369153692536935369453695536965369753698536995370053701537025370353704537055370653707537085370953710537115371253713537145371553716537175371853719537205372153722537235372453725537265372753728537295373053731537325373353734537355373653737537385373953740537415374253743537445374553746537475374853749537505375153752537535375453755537565375753758537595376053761537625376353764537655376653767537685376953770537715377253773537745377553776537775377853779537805378153782537835378453785537865378753788537895379053791537925379353794537955379653797537985379953800538015380253803538045380553806538075380853809538105381153812538135381453815538165381753818538195382053821538225382353824538255382653827538285382953830538315383253833538345383553836538375383853839538405384153842538435384453845538465384753848538495385053851538525385353854538555385653857538585385953860538615386253863538645386553866538675386853869538705387153872538735387453875538765387753878538795388053881538825388353884538855388653887538885388953890538915389253893538945389553896538975389853899539005390153902539035390453905539065390753908539095391053911539125391353914539155391653917539185391953920539215392253923539245392553926539275392853929539305393153932539335393453935539365393753938539395394053941539425394353944539455394653947539485394953950539515395253953539545395553956539575395853959539605396153962539635396453965539665396753968539695397053971539725397353974539755397653977539785397953980539815398253983539845398553986539875398853989539905399153992539935399453995539965399753998539995400054001540025400354004540055400654007540085400954010540115401254013540145401554016540175401854019540205402154022540235402454025540265402754028540295403054031540325403354034540355403654037540385403954040540415404254043540445404554046540475404854049540505405154052540535405454055540565405754058540595406054061540625406354064540655406654067540685406954070540715407254073540745407554076540775407854079540805408154082540835408454085540865408754088540895409054091540925409354094540955409654097540985409954100541015410254103541045410554106541075410854109541105411154112541135411454115541165411754118541195412054121541225412354124541255412654127541285412954130541315413254133541345413554136541375413854139541405414154142541435414454145541465414754148541495415054151541525415354154541555415654157541585415954160541615416254163541645416554166541675416854169541705417154172541735417454175541765417754178541795418054181541825418354184541855418654187541885418954190541915419254193541945419554196541975419854199542005420154202542035420454205542065420754208542095421054211542125421354214542155421654217542185421954220542215422254223542245422554226542275422854229542305423154232542335423454235542365423754238542395424054241542425424354244542455424654247542485424954250542515425254253542545425554256542575425854259542605426154262542635426454265542665426754268542695427054271542725427354274542755427654277542785427954280542815428254283542845428554286542875428854289542905429154292542935429454295542965429754298542995430054301543025430354304543055430654307543085430954310543115431254313543145431554316543175431854319543205432154322543235432454325543265432754328543295433054331543325433354334543355433654337543385433954340543415434254343543445434554346543475434854349543505435154352543535435454355543565435754358543595436054361543625436354364543655436654367543685436954370543715437254373543745437554376543775437854379543805438154382543835438454385543865438754388543895439054391543925439354394543955439654397543985439954400544015440254403544045440554406544075440854409544105441154412544135441454415544165441754418544195442054421544225442354424544255442654427544285442954430544315443254433544345443554436544375443854439544405444154442544435444454445544465444754448544495445054451544525445354454544555445654457544585445954460544615446254463544645446554466544675446854469544705447154472544735447454475544765447754478544795448054481544825448354484544855448654487544885448954490544915449254493544945449554496544975449854499545005450154502545035450454505545065450754508545095451054511545125451354514545155451654517545185451954520545215452254523545245452554526545275452854529545305453154532545335453454535545365453754538545395454054541545425454354544545455454654547545485454954550545515455254553545545455554556545575455854559545605456154562545635456454565545665456754568545695457054571545725457354574545755457654577545785457954580545815458254583545845458554586545875458854589545905459154592545935459454595545965459754598545995460054601546025460354604546055460654607546085460954610546115461254613546145461554616546175461854619546205462154622546235462454625546265462754628546295463054631546325463354634546355463654637546385463954640546415464254643546445464554646546475464854649546505465154652546535465454655546565465754658546595466054661546625466354664546655466654667546685466954670546715467254673546745467554676546775467854679546805468154682546835468454685546865468754688546895469054691546925469354694546955469654697546985469954700547015470254703547045470554706547075470854709547105471154712547135471454715547165471754718547195472054721547225472354724547255472654727547285472954730547315473254733547345473554736547375473854739547405474154742547435474454745547465474754748547495475054751547525475354754547555475654757547585475954760547615476254763547645476554766547675476854769547705477154772547735477454775547765477754778547795478054781547825478354784547855478654787547885478954790547915479254793547945479554796547975479854799548005480154802548035480454805548065480754808548095481054811548125481354814548155481654817548185481954820548215482254823548245482554826548275482854829548305483154832548335483454835548365483754838548395484054841548425484354844548455484654847548485484954850548515485254853548545485554856548575485854859548605486154862548635486454865548665486754868548695487054871548725487354874548755487654877548785487954880548815488254883548845488554886548875488854889548905489154892548935489454895548965489754898548995490054901549025490354904549055490654907549085490954910549115491254913549145491554916549175491854919549205492154922549235492454925549265492754928549295493054931549325493354934549355493654937549385493954940549415494254943549445494554946549475494854949549505495154952549535495454955549565495754958549595496054961549625496354964549655496654967549685496954970549715497254973549745497554976549775497854979549805498154982549835498454985549865498754988549895499054991549925499354994549955499654997549985499955000550015500255003550045500555006550075500855009550105501155012550135501455015550165501755018550195502055021550225502355024550255502655027550285502955030550315503255033550345503555036550375503855039550405504155042550435504455045550465504755048550495505055051550525505355054550555505655057550585505955060550615506255063550645506555066550675506855069550705507155072550735507455075550765507755078550795508055081550825508355084550855508655087550885508955090550915509255093550945509555096550975509855099551005510155102551035510455105551065510755108551095511055111551125511355114551155511655117551185511955120551215512255123551245512555126551275512855129551305513155132551335513455135551365513755138551395514055141551425514355144551455514655147551485514955150551515515255153551545515555156551575515855159551605516155162551635516455165551665516755168551695517055171551725517355174551755517655177551785517955180551815518255183551845518555186551875518855189551905519155192551935519455195551965519755198551995520055201552025520355204552055520655207552085520955210552115521255213552145521555216552175521855219552205522155222552235522455225552265522755228552295523055231552325523355234552355523655237552385523955240552415524255243552445524555246552475524855249552505525155252552535525455255552565525755258552595526055261552625526355264552655526655267552685526955270552715527255273552745527555276552775527855279552805528155282552835528455285552865528755288552895529055291552925529355294552955529655297552985529955300553015530255303553045530555306553075530855309553105531155312553135531455315553165531755318553195532055321553225532355324553255532655327553285532955330553315533255333553345533555336553375533855339553405534155342553435534455345553465534755348553495535055351553525535355354553555535655357553585535955360553615536255363553645536555366553675536855369553705537155372553735537455375553765537755378553795538055381553825538355384553855538655387553885538955390553915539255393553945539555396553975539855399554005540155402554035540455405554065540755408554095541055411554125541355414554155541655417554185541955420554215542255423554245542555426554275542855429554305543155432554335543455435554365543755438554395544055441554425544355444554455544655447554485544955450554515545255453554545545555456554575545855459554605546155462554635546455465554665546755468554695547055471554725547355474554755547655477554785547955480554815548255483554845548555486554875548855489554905549155492554935549455495554965549755498554995550055501555025550355504555055550655507555085550955510555115551255513555145551555516555175551855519555205552155522555235552455525555265552755528555295553055531555325553355534555355553655537555385553955540555415554255543555445554555546555475554855549555505555155552555535555455555555565555755558555595556055561555625556355564555655556655567555685556955570555715557255573555745557555576555775557855579555805558155582555835558455585555865558755588555895559055591555925559355594555955559655597555985559955600556015560255603556045560555606556075560855609556105561155612556135561455615556165561755618556195562055621556225562355624556255562655627556285562955630556315563255633556345563555636556375563855639556405564155642556435564455645556465564755648556495565055651556525565355654556555565655657556585565955660556615566255663556645566555666556675566855669556705567155672556735567455675556765567755678556795568055681556825568355684556855568655687556885568955690556915569255693556945569555696556975569855699557005570155702557035570455705557065570755708557095571055711557125571355714557155571655717557185571955720557215572255723557245572555726557275572855729557305573155732557335573455735557365573755738557395574055741557425574355744557455574655747557485574955750557515575255753557545575555756557575575855759557605576155762557635576455765557665576755768557695577055771557725577355774557755577655777557785577955780557815578255783557845578555786557875578855789557905579155792557935579455795557965579755798557995580055801558025580355804558055580655807558085580955810558115581255813558145581555816558175581855819558205582155822558235582455825558265582755828558295583055831558325583355834558355583655837558385583955840558415584255843558445584555846558475584855849558505585155852558535585455855558565585755858558595586055861558625586355864558655586655867558685586955870558715587255873558745587555876558775587855879558805588155882558835588455885558865588755888558895589055891558925589355894558955589655897558985589955900559015590255903559045590555906559075590855909559105591155912559135591455915559165591755918559195592055921559225592355924559255592655927559285592955930559315593255933559345593555936559375593855939559405594155942559435594455945559465594755948559495595055951559525595355954559555595655957559585595955960559615596255963559645596555966559675596855969559705597155972559735597455975559765597755978559795598055981559825598355984559855598655987559885598955990559915599255993559945599555996559975599855999560005600156002560035600456005560065600756008560095601056011560125601356014560155601656017560185601956020560215602256023560245602556026560275602856029560305603156032560335603456035560365603756038560395604056041560425604356044560455604656047560485604956050560515605256053560545605556056560575605856059560605606156062560635606456065560665606756068560695607056071560725607356074560755607656077560785607956080560815608256083560845608556086560875608856089560905609156092560935609456095560965609756098560995610056101561025610356104561055610656107561085610956110561115611256113561145611556116561175611856119561205612156122561235612456125561265612756128561295613056131561325613356134561355613656137561385613956140561415614256143561445614556146561475614856149561505615156152561535615456155561565615756158561595616056161561625616356164561655616656167561685616956170561715617256173561745617556176561775617856179561805618156182561835618456185561865618756188561895619056191561925619356194561955619656197561985619956200562015620256203562045620556206562075620856209562105621156212562135621456215562165621756218562195622056221562225622356224562255622656227562285622956230562315623256233562345623556236562375623856239562405624156242562435624456245562465624756248562495625056251562525625356254562555625656257562585625956260562615626256263562645626556266562675626856269562705627156272562735627456275562765627756278562795628056281562825628356284562855628656287562885628956290562915629256293562945629556296562975629856299563005630156302563035630456305563065630756308563095631056311563125631356314563155631656317563185631956320563215632256323563245632556326563275632856329563305633156332563335633456335563365633756338563395634056341563425634356344563455634656347563485634956350563515635256353563545635556356563575635856359563605636156362563635636456365563665636756368563695637056371563725637356374563755637656377563785637956380563815638256383563845638556386563875638856389563905639156392563935639456395563965639756398563995640056401564025640356404564055640656407564085640956410564115641256413564145641556416564175641856419564205642156422564235642456425564265642756428564295643056431564325643356434564355643656437564385643956440564415644256443564445644556446564475644856449564505645156452564535645456455564565645756458564595646056461564625646356464564655646656467564685646956470564715647256473564745647556476564775647856479564805648156482564835648456485564865648756488564895649056491564925649356494564955649656497564985649956500565015650256503565045650556506565075650856509565105651156512565135651456515565165651756518565195652056521565225652356524565255652656527565285652956530565315653256533565345653556536565375653856539565405654156542565435654456545565465654756548565495655056551565525655356554565555655656557565585655956560565615656256563565645656556566565675656856569565705657156572565735657456575565765657756578565795658056581565825658356584565855658656587565885658956590565915659256593565945659556596565975659856599566005660156602566035660456605566065660756608566095661056611566125661356614566155661656617566185661956620566215662256623566245662556626566275662856629566305663156632566335663456635566365663756638566395664056641566425664356644566455664656647566485664956650566515665256653566545665556656566575665856659566605666156662566635666456665566665666756668566695667056671566725667356674566755667656677566785667956680566815668256683566845668556686566875668856689566905669156692566935669456695566965669756698566995670056701567025670356704567055670656707567085670956710567115671256713567145671556716567175671856719567205672156722567235672456725567265672756728567295673056731567325673356734567355673656737567385673956740567415674256743567445674556746567475674856749567505675156752567535675456755567565675756758567595676056761567625676356764567655676656767567685676956770567715677256773567745677556776567775677856779567805678156782567835678456785567865678756788567895679056791567925679356794567955679656797567985679956800568015680256803568045680556806568075680856809568105681156812568135681456815568165681756818568195682056821568225682356824568255682656827568285682956830568315683256833568345683556836568375683856839568405684156842568435684456845568465684756848568495685056851568525685356854568555685656857568585685956860568615686256863568645686556866568675686856869568705687156872568735687456875568765687756878568795688056881568825688356884568855688656887568885688956890568915689256893568945689556896568975689856899569005690156902569035690456905569065690756908569095691056911569125691356914569155691656917569185691956920569215692256923569245692556926569275692856929569305693156932569335693456935569365693756938569395694056941569425694356944569455694656947569485694956950569515695256953569545695556956569575695856959569605696156962569635696456965569665696756968569695697056971569725697356974569755697656977569785697956980569815698256983569845698556986569875698856989569905699156992569935699456995569965699756998569995700057001570025700357004570055700657007570085700957010570115701257013570145701557016570175701857019570205702157022570235702457025570265702757028570295703057031570325703357034570355703657037570385703957040570415704257043570445704557046570475704857049570505705157052570535705457055570565705757058570595706057061570625706357064570655706657067570685706957070570715707257073570745707557076570775707857079570805708157082570835708457085570865708757088570895709057091570925709357094570955709657097570985709957100571015710257103571045710557106571075710857109571105711157112571135711457115571165711757118571195712057121571225712357124571255712657127571285712957130571315713257133571345713557136571375713857139571405714157142571435714457145571465714757148571495715057151571525715357154571555715657157571585715957160571615716257163571645716557166571675716857169571705717157172571735717457175571765717757178571795718057181571825718357184571855718657187571885718957190571915719257193571945719557196571975719857199572005720157202572035720457205572065720757208572095721057211572125721357214572155721657217572185721957220572215722257223572245722557226572275722857229572305723157232572335723457235572365723757238572395724057241572425724357244572455724657247572485724957250572515725257253572545725557256572575725857259572605726157262572635726457265572665726757268572695727057271572725727357274572755727657277572785727957280572815728257283572845728557286572875728857289572905729157292572935729457295572965729757298572995730057301573025730357304573055730657307573085730957310573115731257313573145731557316573175731857319573205732157322573235732457325573265732757328573295733057331573325733357334573355733657337573385733957340573415734257343573445734557346573475734857349573505735157352573535735457355573565735757358573595736057361573625736357364573655736657367573685736957370573715737257373573745737557376573775737857379573805738157382573835738457385573865738757388573895739057391573925739357394573955739657397573985739957400574015740257403574045740557406574075740857409574105741157412574135741457415574165741757418574195742057421574225742357424574255742657427574285742957430574315743257433574345743557436574375743857439574405744157442574435744457445574465744757448574495745057451574525745357454574555745657457574585745957460574615746257463574645746557466574675746857469574705747157472574735747457475574765747757478574795748057481574825748357484574855748657487574885748957490574915749257493574945749557496574975749857499575005750157502575035750457505575065750757508575095751057511575125751357514575155751657517575185751957520575215752257523575245752557526575275752857529575305753157532575335753457535575365753757538575395754057541575425754357544575455754657547575485754957550575515755257553575545755557556575575755857559575605756157562575635756457565575665756757568575695757057571575725757357574575755757657577575785757957580575815758257583575845758557586575875758857589575905759157592575935759457595575965759757598575995760057601576025760357604576055760657607576085760957610576115761257613576145761557616576175761857619576205762157622576235762457625576265762757628576295763057631576325763357634576355763657637576385763957640576415764257643576445764557646576475764857649576505765157652576535765457655576565765757658576595766057661576625766357664576655766657667576685766957670576715767257673576745767557676576775767857679576805768157682576835768457685576865768757688576895769057691576925769357694576955769657697576985769957700577015770257703577045770557706577075770857709577105771157712577135771457715577165771757718577195772057721577225772357724577255772657727577285772957730577315773257733577345773557736577375773857739577405774157742577435774457745577465774757748577495775057751577525775357754577555775657757577585775957760577615776257763577645776557766577675776857769577705777157772577735777457775577765777757778577795778057781577825778357784577855778657787577885778957790577915779257793577945779557796577975779857799578005780157802578035780457805578065780757808578095781057811578125781357814578155781657817578185781957820578215782257823578245782557826578275782857829578305783157832578335783457835578365783757838578395784057841578425784357844578455784657847578485784957850578515785257853578545785557856578575785857859578605786157862578635786457865578665786757868578695787057871578725787357874578755787657877578785787957880578815788257883578845788557886578875788857889578905789157892578935789457895578965789757898578995790057901579025790357904579055790657907579085790957910579115791257913579145791557916579175791857919579205792157922579235792457925579265792757928579295793057931579325793357934579355793657937579385793957940579415794257943579445794557946579475794857949579505795157952579535795457955579565795757958579595796057961579625796357964579655796657967579685796957970579715797257973579745797557976579775797857979579805798157982579835798457985579865798757988579895799057991579925799357994579955799657997579985799958000580015800258003580045800558006580075800858009580105801158012580135801458015580165801758018580195802058021580225802358024580255802658027580285802958030580315803258033580345803558036580375803858039580405804158042580435804458045580465804758048580495805058051580525805358054580555805658057580585805958060580615806258063580645806558066580675806858069580705807158072580735807458075580765807758078580795808058081580825808358084580855808658087580885808958090580915809258093580945809558096580975809858099581005810158102581035810458105581065810758108581095811058111581125811358114581155811658117581185811958120581215812258123581245812558126581275812858129581305813158132581335813458135581365813758138581395814058141581425814358144581455814658147581485814958150581515815258153581545815558156581575815858159581605816158162581635816458165581665816758168581695817058171581725817358174581755817658177581785817958180581815818258183581845818558186581875818858189581905819158192581935819458195581965819758198581995820058201582025820358204582055820658207582085820958210582115821258213582145821558216582175821858219582205822158222582235822458225582265822758228582295823058231582325823358234582355823658237582385823958240582415824258243582445824558246582475824858249582505825158252582535825458255582565825758258582595826058261582625826358264582655826658267582685826958270582715827258273582745827558276582775827858279582805828158282582835828458285582865828758288582895829058291582925829358294582955829658297582985829958300583015830258303583045830558306583075830858309583105831158312583135831458315583165831758318583195832058321583225832358324583255832658327583285832958330583315833258333583345833558336583375833858339583405834158342583435834458345583465834758348583495835058351583525835358354583555835658357583585835958360583615836258363583645836558366583675836858369583705837158372583735837458375583765837758378583795838058381583825838358384583855838658387583885838958390583915839258393583945839558396583975839858399584005840158402584035840458405584065840758408584095841058411584125841358414584155841658417584185841958420584215842258423584245842558426584275842858429584305843158432584335843458435584365843758438584395844058441584425844358444584455844658447584485844958450584515845258453584545845558456584575845858459584605846158462584635846458465584665846758468584695847058471584725847358474584755847658477584785847958480584815848258483584845848558486584875848858489584905849158492584935849458495584965849758498584995850058501585025850358504585055850658507585085850958510585115851258513585145851558516585175851858519585205852158522585235852458525585265852758528585295853058531585325853358534585355853658537585385853958540585415854258543585445854558546585475854858549585505855158552585535855458555585565855758558585595856058561585625856358564585655856658567585685856958570585715857258573585745857558576585775857858579585805858158582585835858458585585865858758588585895859058591585925859358594585955859658597585985859958600586015860258603586045860558606586075860858609586105861158612586135861458615586165861758618586195862058621586225862358624586255862658627586285862958630586315863258633586345863558636586375863858639586405864158642586435864458645586465864758648586495865058651586525865358654586555865658657586585865958660586615866258663586645866558666586675866858669586705867158672586735867458675586765867758678586795868058681586825868358684586855868658687586885868958690586915869258693586945869558696586975869858699587005870158702587035870458705587065870758708587095871058711587125871358714587155871658717587185871958720587215872258723587245872558726587275872858729587305873158732587335873458735587365873758738587395874058741587425874358744587455874658747587485874958750587515875258753587545875558756587575875858759587605876158762587635876458765587665876758768587695877058771587725877358774587755877658777587785877958780587815878258783587845878558786587875878858789587905879158792587935879458795587965879758798587995880058801588025880358804588055880658807588085880958810588115881258813588145881558816588175881858819588205882158822588235882458825588265882758828588295883058831588325883358834588355883658837588385883958840588415884258843588445884558846588475884858849588505885158852588535885458855588565885758858588595886058861588625886358864588655886658867588685886958870588715887258873588745887558876588775887858879588805888158882588835888458885588865888758888588895889058891588925889358894588955889658897588985889958900589015890258903589045890558906589075890858909589105891158912589135891458915589165891758918589195892058921589225892358924589255892658927589285892958930589315893258933589345893558936589375893858939589405894158942589435894458945589465894758948589495895058951589525895358954589555895658957589585895958960589615896258963589645896558966589675896858969589705897158972589735897458975589765897758978589795898058981589825898358984589855898658987589885898958990589915899258993589945899558996589975899858999590005900159002590035900459005590065900759008590095901059011590125901359014590155901659017590185901959020590215902259023590245902559026590275902859029590305903159032590335903459035590365903759038590395904059041590425904359044590455904659047590485904959050590515905259053590545905559056590575905859059590605906159062590635906459065590665906759068590695907059071590725907359074590755907659077590785907959080590815908259083590845908559086590875908859089590905909159092590935909459095590965909759098590995910059101591025910359104591055910659107591085910959110591115911259113591145911559116591175911859119591205912159122591235912459125591265912759128591295913059131591325913359134591355913659137591385913959140591415914259143591445914559146591475914859149591505915159152591535915459155591565915759158591595916059161591625916359164591655916659167591685916959170591715917259173591745917559176591775917859179591805918159182591835918459185591865918759188591895919059191591925919359194591955919659197591985919959200592015920259203592045920559206592075920859209592105921159212592135921459215592165921759218592195922059221592225922359224592255922659227592285922959230592315923259233592345923559236592375923859239592405924159242592435924459245592465924759248592495925059251592525925359254592555925659257592585925959260592615926259263592645926559266592675926859269592705927159272592735927459275592765927759278592795928059281592825928359284592855928659287592885928959290592915929259293592945929559296592975929859299593005930159302593035930459305593065930759308593095931059311593125931359314593155931659317593185931959320593215932259323593245932559326593275932859329593305933159332593335933459335593365933759338593395934059341593425934359344593455934659347593485934959350593515935259353593545935559356593575935859359593605936159362593635936459365593665936759368593695937059371593725937359374593755937659377593785937959380593815938259383593845938559386593875938859389593905939159392593935939459395593965939759398593995940059401594025940359404594055940659407594085940959410594115941259413594145941559416594175941859419594205942159422594235942459425594265942759428594295943059431594325943359434594355943659437594385943959440594415944259443594445944559446594475944859449594505945159452594535945459455594565945759458594595946059461594625946359464594655946659467594685946959470594715947259473594745947559476594775947859479594805948159482594835948459485594865948759488594895949059491594925949359494594955949659497594985949959500595015950259503595045950559506595075950859509595105951159512595135951459515595165951759518595195952059521595225952359524595255952659527595285952959530595315953259533595345953559536595375953859539595405954159542595435954459545595465954759548595495955059551595525955359554595555955659557595585955959560595615956259563595645956559566595675956859569595705957159572595735957459575595765957759578595795958059581595825958359584595855958659587595885958959590595915959259593595945959559596595975959859599596005960159602596035960459605596065960759608596095961059611596125961359614596155961659617596185961959620596215962259623596245962559626596275962859629596305963159632596335963459635596365963759638596395964059641596425964359644596455964659647596485964959650596515965259653596545965559656596575965859659596605966159662596635966459665596665966759668596695967059671596725967359674596755967659677596785967959680596815968259683596845968559686596875968859689596905969159692596935969459695596965969759698596995970059701597025970359704597055970659707597085970959710597115971259713597145971559716597175971859719597205972159722597235972459725597265972759728597295973059731597325973359734597355973659737597385973959740597415974259743597445974559746597475974859749597505975159752597535975459755597565975759758597595976059761597625976359764597655976659767597685976959770597715977259773597745977559776597775977859779597805978159782597835978459785597865978759788597895979059791597925979359794597955979659797597985979959800598015980259803598045980559806598075980859809598105981159812598135981459815598165981759818598195982059821598225982359824598255982659827598285982959830598315983259833598345983559836598375983859839598405984159842598435984459845598465984759848598495985059851598525985359854598555985659857598585985959860598615986259863598645986559866598675986859869598705987159872598735987459875598765987759878598795988059881598825988359884598855988659887598885988959890598915989259893598945989559896598975989859899599005990159902599035990459905599065990759908599095991059911599125991359914599155991659917599185991959920599215992259923599245992559926599275992859929599305993159932599335993459935599365993759938599395994059941599425994359944599455994659947599485994959950599515995259953599545995559956599575995859959599605996159962599635996459965599665996759968599695997059971599725997359974599755997659977599785997959980599815998259983599845998559986599875998859989599905999159992599935999459995599965999759998599996000060001600026000360004600056000660007600086000960010600116001260013600146001560016600176001860019600206002160022600236002460025600266002760028600296003060031600326003360034600356003660037600386003960040600416004260043600446004560046600476004860049600506005160052600536005460055600566005760058600596006060061600626006360064600656006660067600686006960070600716007260073600746007560076600776007860079600806008160082600836008460085600866008760088600896009060091600926009360094600956009660097600986009960100601016010260103601046010560106601076010860109601106011160112601136011460115601166011760118601196012060121601226012360124601256012660127601286012960130601316013260133601346013560136601376013860139601406014160142601436014460145601466014760148601496015060151601526015360154601556015660157601586015960160601616016260163601646016560166601676016860169601706017160172601736017460175601766017760178601796018060181601826018360184601856018660187601886018960190601916019260193601946019560196601976019860199602006020160202602036020460205602066020760208602096021060211602126021360214602156021660217602186021960220602216022260223602246022560226602276022860229602306023160232602336023460235602366023760238602396024060241602426024360244602456024660247602486024960250602516025260253602546025560256602576025860259602606026160262602636026460265602666026760268602696027060271602726027360274602756027660277602786027960280602816028260283602846028560286602876028860289602906029160292602936029460295602966029760298602996030060301603026030360304603056030660307603086030960310603116031260313603146031560316603176031860319603206032160322603236032460325603266032760328603296033060331603326033360334603356033660337603386033960340603416034260343603446034560346603476034860349603506035160352603536035460355603566035760358603596036060361603626036360364603656036660367603686036960370603716037260373603746037560376603776037860379603806038160382603836038460385603866038760388603896039060391603926039360394603956039660397603986039960400604016040260403604046040560406604076040860409604106041160412604136041460415604166041760418604196042060421604226042360424604256042660427604286042960430604316043260433604346043560436604376043860439604406044160442604436044460445604466044760448604496045060451604526045360454604556045660457604586045960460604616046260463604646046560466604676046860469604706047160472604736047460475604766047760478604796048060481604826048360484604856048660487604886048960490604916049260493604946049560496604976049860499605006050160502605036050460505605066050760508605096051060511605126051360514605156051660517605186051960520605216052260523605246052560526605276052860529605306053160532605336053460535605366053760538605396054060541605426054360544605456054660547605486054960550605516055260553605546055560556605576055860559605606056160562605636056460565605666056760568605696057060571605726057360574605756057660577605786057960580605816058260583605846058560586605876058860589605906059160592605936059460595605966059760598605996060060601606026060360604606056060660607606086060960610606116061260613606146061560616606176061860619606206062160622606236062460625606266062760628606296063060631606326063360634606356063660637606386063960640606416064260643606446064560646606476064860649606506065160652606536065460655606566065760658606596066060661606626066360664606656066660667606686066960670606716067260673606746067560676606776067860679606806068160682606836068460685606866068760688606896069060691606926069360694606956069660697606986069960700607016070260703607046070560706607076070860709607106071160712607136071460715607166071760718607196072060721607226072360724607256072660727607286072960730607316073260733607346073560736607376073860739607406074160742607436074460745607466074760748607496075060751607526075360754607556075660757607586075960760607616076260763607646076560766607676076860769607706077160772607736077460775607766077760778607796078060781607826078360784607856078660787607886078960790607916079260793607946079560796607976079860799608006080160802608036080460805608066080760808608096081060811608126081360814608156081660817608186081960820608216082260823608246082560826608276082860829608306083160832608336083460835608366083760838608396084060841608426084360844608456084660847608486084960850608516085260853608546085560856608576085860859608606086160862608636086460865608666086760868608696087060871608726087360874608756087660877608786087960880608816088260883608846088560886608876088860889608906089160892608936089460895608966089760898608996090060901609026090360904609056090660907609086090960910609116091260913609146091560916609176091860919609206092160922609236092460925609266092760928609296093060931609326093360934609356093660937609386093960940609416094260943609446094560946609476094860949609506095160952609536095460955609566095760958609596096060961609626096360964609656096660967609686096960970609716097260973609746097560976609776097860979609806098160982609836098460985609866098760988609896099060991609926099360994609956099660997609986099961000610016100261003610046100561006610076100861009610106101161012610136101461015610166101761018610196102061021610226102361024610256102661027610286102961030610316103261033610346103561036610376103861039610406104161042610436104461045610466104761048610496105061051610526105361054610556105661057610586105961060610616106261063610646106561066610676106861069610706107161072610736107461075610766107761078610796108061081610826108361084610856108661087610886108961090610916109261093610946109561096610976109861099611006110161102611036110461105611066110761108611096111061111611126111361114611156111661117611186111961120611216112261123611246112561126611276112861129611306113161132611336113461135611366113761138611396114061141611426114361144611456114661147611486114961150611516115261153611546115561156611576115861159611606116161162611636116461165611666116761168611696117061171611726117361174611756117661177611786117961180611816118261183611846118561186611876118861189611906119161192611936119461195611966119761198611996120061201612026120361204612056120661207612086120961210612116121261213612146121561216612176121861219612206122161222612236122461225612266122761228612296123061231612326123361234612356123661237612386123961240612416124261243612446124561246612476124861249612506125161252612536125461255612566125761258612596126061261612626126361264612656126661267612686126961270612716127261273612746127561276612776127861279612806128161282612836128461285612866128761288612896129061291612926129361294612956129661297612986129961300613016130261303613046130561306613076130861309613106131161312613136131461315613166131761318613196132061321613226132361324613256132661327613286132961330613316133261333613346133561336613376133861339613406134161342613436134461345613466134761348613496135061351613526135361354613556135661357613586135961360613616136261363613646136561366613676136861369613706137161372613736137461375613766137761378613796138061381613826138361384613856138661387613886138961390613916139261393613946139561396613976139861399614006140161402614036140461405614066140761408614096141061411614126141361414614156141661417614186141961420614216142261423614246142561426614276142861429614306143161432614336143461435614366143761438614396144061441614426144361444614456144661447614486144961450614516145261453614546145561456614576145861459614606146161462614636146461465614666146761468614696147061471614726147361474614756147661477614786147961480614816148261483614846148561486614876148861489614906149161492614936149461495614966149761498614996150061501615026150361504615056150661507615086150961510615116151261513615146151561516615176151861519615206152161522615236152461525615266152761528615296153061531615326153361534615356153661537615386153961540615416154261543615446154561546615476154861549615506155161552615536155461555615566155761558615596156061561615626156361564615656156661567615686156961570615716157261573615746157561576615776157861579615806158161582615836158461585615866158761588615896159061591615926159361594615956159661597615986159961600616016160261603616046160561606616076160861609616106161161612616136161461615616166161761618616196162061621616226162361624616256162661627616286162961630616316163261633616346163561636616376163861639616406164161642616436164461645616466164761648616496165061651616526165361654616556165661657616586165961660616616166261663616646166561666616676166861669616706167161672616736167461675616766167761678616796168061681616826168361684616856168661687616886168961690616916169261693616946169561696616976169861699617006170161702617036170461705617066170761708617096171061711617126171361714617156171661717617186171961720617216172261723617246172561726617276172861729617306173161732617336173461735617366173761738617396174061741617426174361744617456174661747617486174961750617516175261753617546175561756617576175861759617606176161762617636176461765617666176761768617696177061771617726177361774617756177661777617786177961780617816178261783617846178561786617876178861789617906179161792617936179461795617966179761798617996180061801618026180361804618056180661807618086180961810618116181261813618146181561816618176181861819618206182161822618236182461825618266182761828618296183061831618326183361834618356183661837618386183961840618416184261843618446184561846618476184861849618506185161852618536185461855618566185761858618596186061861618626186361864618656186661867618686186961870618716187261873618746187561876618776187861879618806188161882618836188461885618866188761888618896189061891618926189361894618956189661897618986189961900619016190261903619046190561906619076190861909619106191161912619136191461915619166191761918619196192061921619226192361924619256192661927619286192961930619316193261933619346193561936619376193861939619406194161942619436194461945619466194761948619496195061951619526195361954619556195661957619586195961960619616196261963619646196561966619676196861969619706197161972619736197461975619766197761978619796198061981619826198361984619856198661987619886198961990619916199261993619946199561996619976199861999620006200162002620036200462005620066200762008620096201062011620126201362014620156201662017620186201962020620216202262023620246202562026620276202862029620306203162032620336203462035620366203762038620396204062041620426204362044620456204662047620486204962050620516205262053620546205562056620576205862059620606206162062620636206462065620666206762068620696207062071620726207362074620756207662077620786207962080620816208262083620846208562086620876208862089620906209162092620936209462095620966209762098620996210062101621026210362104621056210662107621086210962110621116211262113621146211562116621176211862119621206212162122621236212462125621266212762128621296213062131621326213362134621356213662137621386213962140621416214262143621446214562146621476214862149621506215162152621536215462155621566215762158621596216062161621626216362164621656216662167621686216962170621716217262173621746217562176621776217862179621806218162182621836218462185621866218762188621896219062191621926219362194621956219662197621986219962200622016220262203622046220562206622076220862209622106221162212622136221462215622166221762218622196222062221622226222362224622256222662227622286222962230622316223262233622346223562236622376223862239622406224162242622436224462245622466224762248622496225062251622526225362254622556225662257622586225962260622616226262263622646226562266622676226862269622706227162272622736227462275622766227762278622796228062281622826228362284622856228662287622886228962290622916229262293622946229562296622976229862299623006230162302623036230462305623066230762308623096231062311623126231362314623156231662317623186231962320623216232262323623246232562326623276232862329623306233162332623336233462335623366233762338623396234062341623426234362344623456234662347623486234962350623516235262353623546235562356623576235862359623606236162362623636236462365623666236762368623696237062371623726237362374623756237662377623786237962380623816238262383623846238562386623876238862389623906239162392623936239462395623966239762398623996240062401624026240362404624056240662407624086240962410624116241262413624146241562416624176241862419624206242162422624236242462425624266242762428624296243062431624326243362434624356243662437624386243962440624416244262443624446244562446624476244862449624506245162452624536245462455624566245762458624596246062461624626246362464624656246662467624686246962470624716247262473624746247562476624776247862479624806248162482624836248462485624866248762488624896249062491624926249362494624956249662497624986249962500625016250262503625046250562506625076250862509625106251162512625136251462515625166251762518625196252062521625226252362524625256252662527625286252962530625316253262533625346253562536625376253862539625406254162542625436254462545625466254762548625496255062551625526255362554625556255662557625586255962560625616256262563625646256562566625676256862569625706257162572625736257462575625766257762578625796258062581625826258362584625856258662587625886258962590625916259262593625946259562596625976259862599626006260162602626036260462605626066260762608626096261062611626126261362614626156261662617626186261962620626216262262623626246262562626626276262862629626306263162632626336263462635626366263762638626396264062641626426264362644626456264662647626486264962650626516265262653626546265562656626576265862659626606266162662626636266462665626666266762668626696267062671626726267362674626756267662677626786267962680626816268262683626846268562686626876268862689626906269162692626936269462695626966269762698626996270062701627026270362704627056270662707627086270962710627116271262713627146271562716627176271862719627206272162722627236272462725627266272762728627296273062731627326273362734627356273662737627386273962740627416274262743627446274562746627476274862749627506275162752627536275462755627566275762758627596276062761627626276362764627656276662767627686276962770627716277262773627746277562776627776277862779627806278162782627836278462785627866278762788627896279062791627926279362794627956279662797627986279962800628016280262803628046280562806628076280862809628106281162812628136281462815628166281762818628196282062821628226282362824628256282662827628286282962830628316283262833628346283562836628376283862839628406284162842628436284462845628466284762848628496285062851628526285362854628556285662857628586285962860628616286262863628646286562866628676286862869628706287162872628736287462875628766287762878628796288062881628826288362884628856288662887628886288962890628916289262893628946289562896628976289862899629006290162902629036290462905629066290762908629096291062911629126291362914629156291662917629186291962920629216292262923629246292562926629276292862929629306293162932629336293462935629366293762938629396294062941629426294362944629456294662947629486294962950629516295262953629546295562956629576295862959629606296162962629636296462965629666296762968629696297062971629726297362974629756297662977629786297962980629816298262983629846298562986629876298862989629906299162992629936299462995629966299762998629996300063001630026300363004630056300663007630086300963010630116301263013630146301563016630176301863019630206302163022630236302463025630266302763028630296303063031630326303363034630356303663037630386303963040630416304263043630446304563046630476304863049630506305163052630536305463055630566305763058630596306063061630626306363064630656306663067630686306963070630716307263073630746307563076630776307863079630806308163082630836308463085630866308763088630896309063091630926309363094630956309663097630986309963100631016310263103631046310563106631076310863109631106311163112631136311463115631166311763118631196312063121631226312363124631256312663127631286312963130631316313263133631346313563136631376313863139631406314163142631436314463145631466314763148631496315063151631526315363154631556315663157631586315963160631616316263163631646316563166631676316863169631706317163172631736317463175631766317763178631796318063181631826318363184631856318663187631886318963190631916319263193631946319563196631976319863199632006320163202632036320463205632066320763208632096321063211632126321363214632156321663217632186321963220632216322263223632246322563226632276322863229632306323163232632336323463235632366323763238632396324063241632426324363244632456324663247632486324963250632516325263253632546325563256632576325863259632606326163262632636326463265632666326763268632696327063271632726327363274632756327663277632786327963280632816328263283632846328563286632876328863289632906329163292632936329463295632966329763298632996330063301633026330363304633056330663307633086330963310633116331263313633146331563316633176331863319633206332163322633236332463325633266332763328633296333063331633326333363334633356333663337633386333963340633416334263343633446334563346633476334863349633506335163352633536335463355633566335763358633596336063361633626336363364633656336663367633686336963370633716337263373633746337563376633776337863379633806338163382633836338463385633866338763388633896339063391633926339363394633956339663397633986339963400634016340263403634046340563406634076340863409634106341163412634136341463415634166341763418634196342063421634226342363424634256342663427634286342963430634316343263433634346343563436634376343863439634406344163442634436344463445634466344763448634496345063451634526345363454634556345663457634586345963460634616346263463634646346563466634676346863469634706347163472634736347463475634766347763478634796348063481634826348363484634856348663487634886348963490634916349263493634946349563496634976349863499635006350163502635036350463505635066350763508635096351063511635126351363514635156351663517635186351963520635216352263523635246352563526635276352863529635306353163532635336353463535635366353763538635396354063541635426354363544635456354663547635486354963550635516355263553635546355563556635576355863559635606356163562635636356463565635666356763568635696357063571635726357363574635756357663577635786357963580635816358263583635846358563586635876358863589635906359163592635936359463595635966359763598635996360063601636026360363604636056360663607636086360963610636116361263613636146361563616636176361863619636206362163622636236362463625636266362763628636296363063631636326363363634636356363663637636386363963640636416364263643636446364563646636476364863649636506365163652636536365463655636566365763658636596366063661636626366363664636656366663667636686366963670636716367263673636746367563676636776367863679636806368163682636836368463685636866368763688636896369063691636926369363694636956369663697636986369963700637016370263703637046370563706637076370863709637106371163712637136371463715637166371763718637196372063721637226372363724637256372663727637286372963730637316373263733637346373563736637376373863739637406374163742637436374463745637466374763748637496375063751637526375363754637556375663757637586375963760637616376263763637646376563766637676376863769637706377163772637736377463775637766377763778637796378063781637826378363784637856378663787637886378963790637916379263793637946379563796637976379863799638006380163802638036380463805638066380763808638096381063811638126381363814638156381663817638186381963820638216382263823638246382563826638276382863829638306383163832638336383463835638366383763838638396384063841638426384363844638456384663847638486384963850638516385263853638546385563856638576385863859638606386163862638636386463865638666386763868638696387063871638726387363874638756387663877638786387963880638816388263883638846388563886638876388863889638906389163892638936389463895638966389763898638996390063901639026390363904639056390663907639086390963910639116391263913639146391563916639176391863919639206392163922639236392463925639266392763928639296393063931639326393363934639356393663937639386393963940639416394263943639446394563946639476394863949639506395163952639536395463955639566395763958639596396063961639626396363964639656396663967639686396963970639716397263973639746397563976639776397863979639806398163982639836398463985639866398763988639896399063991639926399363994639956399663997639986399964000640016400264003640046400564006640076400864009640106401164012640136401464015640166401764018640196402064021640226402364024640256402664027640286402964030640316403264033640346403564036640376403864039640406404164042640436404464045640466404764048640496405064051640526405364054640556405664057640586405964060640616406264063640646406564066640676406864069640706407164072640736407464075640766407764078640796408064081640826408364084640856408664087640886408964090640916409264093640946409564096640976409864099641006410164102641036410464105641066410764108641096411064111641126411364114641156411664117641186411964120641216412264123641246412564126641276412864129641306413164132641336413464135641366413764138641396414064141641426414364144641456414664147641486414964150641516415264153641546415564156641576415864159641606416164162641636416464165641666416764168641696417064171641726417364174641756417664177641786417964180641816418264183641846418564186641876418864189641906419164192641936419464195641966419764198641996420064201642026420364204642056420664207642086420964210642116421264213642146421564216642176421864219642206422164222642236422464225642266422764228642296423064231642326423364234642356423664237642386423964240642416424264243642446424564246642476424864249642506425164252642536425464255642566425764258642596426064261642626426364264642656426664267642686426964270642716427264273642746427564276642776427864279642806428164282642836428464285642866428764288642896429064291642926429364294642956429664297642986429964300643016430264303643046430564306643076430864309643106431164312643136431464315643166431764318643196432064321643226432364324643256432664327643286432964330643316433264333643346433564336643376433864339643406434164342643436434464345643466434764348643496435064351643526435364354643556435664357643586435964360643616436264363643646436564366643676436864369643706437164372643736437464375643766437764378643796438064381643826438364384643856438664387643886438964390643916439264393643946439564396643976439864399644006440164402644036440464405644066440764408644096441064411644126441364414644156441664417644186441964420644216442264423644246442564426644276442864429644306443164432644336443464435644366443764438644396444064441644426444364444644456444664447644486444964450644516445264453644546445564456644576445864459644606446164462644636446464465644666446764468644696447064471644726447364474644756447664477644786447964480644816448264483644846448564486644876448864489644906449164492644936449464495644966449764498644996450064501645026450364504645056450664507645086450964510645116451264513645146451564516645176451864519645206452164522645236452464525645266452764528645296453064531645326453364534645356453664537645386453964540645416454264543645446454564546645476454864549645506455164552645536455464555645566455764558645596456064561645626456364564645656456664567645686456964570645716457264573645746457564576645776457864579645806458164582645836458464585645866458764588645896459064591645926459364594645956459664597645986459964600646016460264603646046460564606646076460864609646106461164612646136461464615646166461764618646196462064621646226462364624646256462664627646286462964630646316463264633646346463564636646376463864639646406464164642646436464464645646466464764648646496465064651646526465364654646556465664657646586465964660646616466264663646646466564666646676466864669646706467164672646736467464675646766467764678646796468064681646826468364684646856468664687646886468964690646916469264693646946469564696646976469864699647006470164702647036470464705647066470764708647096471064711647126471364714647156471664717647186471964720647216472264723647246472564726647276472864729647306473164732647336473464735647366473764738647396474064741647426474364744647456474664747647486474964750647516475264753647546475564756647576475864759647606476164762647636476464765647666476764768647696477064771647726477364774647756477664777647786477964780647816478264783647846478564786647876478864789647906479164792647936479464795647966479764798647996480064801648026480364804648056480664807648086480964810648116481264813648146481564816648176481864819648206482164822648236482464825648266482764828648296483064831648326483364834648356483664837648386483964840648416484264843648446484564846648476484864849648506485164852648536485464855648566485764858648596486064861648626486364864648656486664867648686486964870648716487264873648746487564876648776487864879648806488164882648836488464885648866488764888648896489064891648926489364894648956489664897648986489964900649016490264903649046490564906649076490864909649106491164912649136491464915649166491764918649196492064921649226492364924649256492664927649286492964930649316493264933649346493564936649376493864939649406494164942649436494464945649466494764948649496495064951649526495364954649556495664957649586495964960649616496264963649646496564966649676496864969649706497164972649736497464975649766497764978649796498064981649826498364984649856498664987649886498964990649916499264993649946499564996649976499864999650006500165002650036500465005650066500765008650096501065011650126501365014650156501665017650186501965020650216502265023650246502565026650276502865029650306503165032650336503465035650366503765038650396504065041650426504365044650456504665047650486504965050650516505265053650546505565056650576505865059650606506165062650636506465065650666506765068650696507065071650726507365074650756507665077650786507965080650816508265083650846508565086650876508865089650906509165092650936509465095650966509765098650996510065101651026510365104651056510665107651086510965110651116511265113651146511565116651176511865119651206512165122651236512465125651266512765128651296513065131651326513365134651356513665137651386513965140651416514265143651446514565146651476514865149651506515165152651536515465155651566515765158651596516065161651626516365164651656516665167651686516965170651716517265173651746517565176651776517865179651806518165182651836518465185651866518765188651896519065191651926519365194651956519665197651986519965200652016520265203652046520565206652076520865209652106521165212652136521465215652166521765218652196522065221652226522365224652256522665227652286522965230652316523265233652346523565236652376523865239652406524165242652436524465245652466524765248652496525065251652526525365254652556525665257652586525965260652616526265263652646526565266652676526865269652706527165272652736527465275652766527765278652796528065281652826528365284652856528665287652886528965290652916529265293652946529565296652976529865299653006530165302653036530465305653066530765308653096531065311653126531365314653156531665317653186531965320653216532265323653246532565326653276532865329653306533165332653336533465335653366533765338653396534065341653426534365344653456534665347653486534965350653516535265353653546535565356653576535865359653606536165362653636536465365653666536765368653696537065371653726537365374653756537665377653786537965380653816538265383653846538565386653876538865389653906539165392653936539465395653966539765398653996540065401654026540365404654056540665407654086540965410654116541265413654146541565416654176541865419654206542165422654236542465425654266542765428654296543065431654326543365434654356543665437654386543965440654416544265443654446544565446654476544865449654506545165452654536545465455654566545765458654596546065461654626546365464654656546665467654686546965470654716547265473654746547565476654776547865479654806548165482654836548465485654866548765488654896549065491654926549365494654956549665497654986549965500655016550265503655046550565506655076550865509655106551165512655136551465515655166551765518655196552065521655226552365524655256552665527655286552965530655316553265533655346553565536655376553865539655406554165542655436554465545655466554765548655496555065551655526555365554655556555665557655586555965560655616556265563655646556565566655676556865569655706557165572655736557465575655766557765578655796558065581655826558365584655856558665587655886558965590655916559265593655946559565596655976559865599656006560165602656036560465605656066560765608656096561065611656126561365614656156561665617656186561965620656216562265623656246562565626656276562865629656306563165632656336563465635656366563765638656396564065641656426564365644656456564665647656486564965650656516565265653656546565565656656576565865659656606566165662656636566465665656666566765668656696567065671656726567365674656756567665677656786567965680656816568265683656846568565686656876568865689656906569165692656936569465695656966569765698656996570065701657026570365704657056570665707657086570965710657116571265713657146571565716657176571865719657206572165722657236572465725657266572765728657296573065731657326573365734657356573665737657386573965740657416574265743657446574565746657476574865749657506575165752657536575465755657566575765758657596576065761657626576365764657656576665767657686576965770657716577265773657746577565776657776577865779657806578165782657836578465785657866578765788657896579065791657926579365794657956579665797657986579965800658016580265803658046580565806658076580865809658106581165812658136581465815658166581765818658196582065821658226582365824658256582665827658286582965830658316583265833658346583565836658376583865839658406584165842658436584465845658466584765848658496585065851658526585365854658556585665857658586585965860658616586265863658646586565866658676586865869658706587165872658736587465875658766587765878658796588065881658826588365884658856588665887658886588965890658916589265893658946589565896658976589865899659006590165902659036590465905659066590765908659096591065911659126591365914659156591665917659186591965920659216592265923659246592565926659276592865929659306593165932659336593465935659366593765938659396594065941659426594365944659456594665947659486594965950659516595265953659546595565956659576595865959659606596165962659636596465965659666596765968659696597065971659726597365974659756597665977659786597965980659816598265983659846598565986659876598865989659906599165992659936599465995659966599765998659996600066001660026600366004660056600666007660086600966010660116601266013660146601566016660176601866019660206602166022660236602466025660266602766028660296603066031660326603366034660356603666037660386603966040660416604266043660446604566046660476604866049660506605166052660536605466055660566605766058660596606066061660626606366064660656606666067660686606966070660716607266073660746607566076660776607866079660806608166082660836608466085660866608766088660896609066091660926609366094660956609666097660986609966100661016610266103661046610566106661076610866109661106611166112661136611466115661166611766118661196612066121661226612366124661256612666127661286612966130661316613266133661346613566136661376613866139661406614166142661436614466145661466614766148661496615066151661526615366154661556615666157661586615966160661616616266163661646616566166661676616866169661706617166172661736617466175661766617766178661796618066181661826618366184661856618666187661886618966190661916619266193661946619566196661976619866199662006620166202662036620466205662066620766208662096621066211662126621366214662156621666217662186621966220662216622266223662246622566226662276622866229662306623166232662336623466235662366623766238662396624066241662426624366244662456624666247662486624966250662516625266253662546625566256662576625866259662606626166262662636626466265662666626766268662696627066271662726627366274662756627666277662786627966280662816628266283662846628566286662876628866289662906629166292662936629466295662966629766298662996630066301663026630366304663056630666307663086630966310663116631266313663146631566316663176631866319663206632166322663236632466325663266632766328663296633066331663326633366334663356633666337663386633966340663416634266343663446634566346663476634866349663506635166352663536635466355 |
- // #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
- #define ENTT_STR(arg) #arg
- #define ENTT_XSTR(arg) ENTT_STR(arg)
- #endif
- #define ENTT_VERSION_MAJOR 3
- #define ENTT_VERSION_MINOR 10
- #define ENTT_VERSION_PATCH 3
- #define ENTT_VERSION \
- ENTT_XSTR(ENTT_VERSION_MAJOR) \
- "." ENTT_XSTR(ENTT_VERSION_MINOR) "." ENTT_XSTR(ENTT_VERSION_PATCH)
- #endif
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #ifndef ENTT_NOEXCEPT
- # define ENTT_NOEXCEPT noexcept
- # define ENTT_NOEXCEPT_IF(expr) noexcept(expr)
- # else
- # define ENTT_NOEXCEPT_IF(...)
- #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
- #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(...) (void(0))
- #elif !defined ENTT_ASSERT
- # include <cassert>
- # define ENTT_ASSERT(condition, ...) assert(condition)
- #endif
- #ifdef ENTT_NO_ETO
- # define ENTT_IGNORE_IF_EMPTY false
- #else
- # define ENTT_IGNORE_IF_EMPTY true
- #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
- #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
- #endif
- // #include "config/macro.h"
- #ifndef ENTT_CONFIG_MACRO_H
- #define ENTT_CONFIG_MACRO_H
- #define ENTT_STR(arg) #arg
- #define ENTT_XSTR(arg) ENTT_STR(arg)
- #endif
- // #include "config/version.h"
- #ifndef ENTT_CONFIG_VERSION_H
- #define ENTT_CONFIG_VERSION_H
- // #include "macro.h"
- #define ENTT_VERSION_MAJOR 3
- #define ENTT_VERSION_MINOR 10
- #define ENTT_VERSION_PATCH 3
- #define ENTT_VERSION \
- ENTT_XSTR(ENTT_VERSION_MAJOR) \
- "." ENTT_XSTR(ENTT_VERSION_MINOR) "." ENTT_XSTR(ENTT_VERSION_PATCH)
- #endif
- // #include "container/dense_map.hpp"
- #ifndef ENTT_CONTAINER_DENSE_MAP_HPP
- #define ENTT_CONTAINER_DENSE_MAP_HPP
- #include <algorithm>
- #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
- #define ENTT_STR(arg) #arg
- #define ENTT_XSTR(arg) ENTT_STR(arg)
- #endif
- #define ENTT_VERSION_MAJOR 3
- #define ENTT_VERSION_MINOR 10
- #define ENTT_VERSION_PATCH 3
- #define ENTT_VERSION \
- ENTT_XSTR(ENTT_VERSION_MAJOR) \
- "." ENTT_XSTR(ENTT_VERSION_MINOR) "." ENTT_XSTR(ENTT_VERSION_PATCH)
- #endif
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #ifndef ENTT_NOEXCEPT
- # define ENTT_NOEXCEPT noexcept
- # define ENTT_NOEXCEPT_IF(expr) noexcept(expr)
- # else
- # define ENTT_NOEXCEPT_IF(...)
- #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
- #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(...) (void(0))
- #elif !defined ENTT_ASSERT
- # include <cassert>
- # define ENTT_ASSERT(condition, ...) assert(condition)
- #endif
- #ifdef ENTT_NO_ETO
- # define ENTT_IGNORE_IF_EMPTY false
- #else
- # define ENTT_IGNORE_IF_EMPTY true
- #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
- #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
- #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 "../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
- #define ENTT_STR(arg) #arg
- #define ENTT_XSTR(arg) ENTT_STR(arg)
- #endif
- #define ENTT_VERSION_MAJOR 3
- #define ENTT_VERSION_MINOR 10
- #define ENTT_VERSION_PATCH 3
- #define ENTT_VERSION \
- ENTT_XSTR(ENTT_VERSION_MAJOR) \
- "." ENTT_XSTR(ENTT_VERSION_MINOR) "." ENTT_XSTR(ENTT_VERSION_PATCH)
- #endif
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #ifndef ENTT_NOEXCEPT
- # define ENTT_NOEXCEPT noexcept
- # define ENTT_NOEXCEPT_IF(expr) noexcept(expr)
- # else
- # define ENTT_NOEXCEPT_IF(...)
- #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
- #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(...) (void(0))
- #elif !defined ENTT_ASSERT
- # include <cassert>
- # define ENTT_ASSERT(condition, ...) assert(condition)
- #endif
- #ifdef ENTT_NO_ETO
- # define ENTT_IGNORE_IF_EMPTY false
- #else
- # define ENTT_IGNORE_IF_EMPTY true
- #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
- #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
- #endif
- // #include "type_traits.hpp"
- #ifndef ENTT_CORE_TYPE_TRAITS_HPP
- #define ENTT_CORE_TYPE_TRAITS_HPP
- #include <cstddef>
- #include <iterator>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- // #include "fwd.hpp"
- #ifndef ENTT_CORE_FWD_HPP
- #define ENTT_CORE_FWD_HPP
- #include <cstdint>
- #include <type_traits>
- // #include "../config/config.h"
- namespace entt {
- template<std::size_t Len = sizeof(double[2]), std::size_t = alignof(typename std::aligned_storage_t<Len + !Len>)>
- 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<>;
- } // 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.
- * @tparam The size of the type if `sizeof` accepts it, 0 otherwise.
- */
- 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))>>
- : 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 Type First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<std::size_t Index, typename Type, typename... Other>
- struct type_list_element<Index, type_list<Type, Other...>>
- : type_list_element<Index - 1u, type_list<Other...>> {};
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam Type First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<typename Type, typename... Other>
- struct type_list_element<0u, type_list<Type, Other...>> {
- /*! @brief Searched type. */
- using type = Type;
- };
- /**
- * @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 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;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename>
- struct type_list_unique;
- /**
- * @brief Removes duplicates types from a type list.
- * @tparam Type One of the types provided by the given type list.
- * @tparam Other The other types provided by the given type list.
- */
- template<typename Type, typename... Other>
- struct type_list_unique<type_list<Type, Other...>> {
- /*! @brief A type list without duplicate types. */
- using type = std::conditional_t<
- (std::is_same_v<Type, Other> || ...),
- typename type_list_unique<type_list<Other...>>::type,
- type_list_cat_t<type_list<Type>, typename type_list_unique<type_list<Other...>>::type>>;
- };
- /*! @brief Removes duplicates types from a type list. */
- template<>
- struct type_list_unique<type_list<>> {
- /*! @brief A type list without duplicate types. */
- using type = type_list<>;
- };
- /**
- * @brief Helper type.
- * @tparam Type A type list.
- */
- template<typename Type>
- using type_list_unique_t = typename type_list_unique<Type>::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::disjunction<std::is_same<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 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 value. */
- static constexpr auto value = Value;
- };
- /**
- * @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 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 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
- * Internal details not to be documented.
- */
- 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
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /*! @copydoc is_iterator */
- template<typename Type>
- struct is_iterator<Type, std::enable_if_t<!std::is_same_v<std::remove_const_t<std::remove_pointer_t<Type>>, void>>>
- : 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::conjunction<std::is_empty<Type>, std::negation<std::is_final<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;
- /**
- * @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, typename = void>
- struct is_equality_comparable: std::false_type {};
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- 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 Type, std::size_t... Index>
- [[nodiscard]] constexpr bool unpack_maybe_equality_comparable(std::index_sequence<Index...>) {
- return (is_equality_comparable<std::tuple_element_t<Index, Type>>::value && ...);
- }
- template<typename>
- [[nodiscard]] constexpr bool maybe_equality_comparable(choice_t<0>) {
- return true;
- }
- template<typename Type>
- [[nodiscard]] constexpr auto maybe_equality_comparable(choice_t<1>) -> decltype(std::declval<typename Type::value_type>(), bool{}) {
- if constexpr(is_iterator_v<Type>) {
- return true;
- } else if constexpr(std::is_same_v<typename Type::value_type, Type>) {
- return maybe_equality_comparable<Type>(choice<0>);
- } else {
- return is_equality_comparable<typename Type::value_type>::value;
- }
- }
- template<typename Type>
- [[nodiscard]] constexpr std::enable_if_t<is_complete_v<std::tuple_size<std::remove_const_t<Type>>>, bool> maybe_equality_comparable(choice_t<2>) {
- if constexpr(has_tuple_size_value<Type>::value) {
- return unpack_maybe_equality_comparable<Type>(std::make_index_sequence<std::tuple_size<Type>::value>{});
- } else {
- return maybe_equality_comparable<Type>(choice<1>);
- }
- }
- } // namespace internal
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /*! @copydoc is_equality_comparable */
- template<typename Type>
- struct is_equality_comparable<Type, std::void_t<decltype(std::declval<Type>() == std::declval<Type>())>>
- : std::bool_constant<internal::maybe_equality_comparable<Type>(choice<2>)> {};
- /**
- * @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 = std::add_const_t<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;
- } // namespace entt
- #endif
- namespace entt {
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- namespace internal {
- template<typename Type, std::size_t, typename = void>
- struct compressed_pair_element {
- using reference = Type &;
- using const_reference = const Type &;
- template<bool Dummy = true, typename = std::enable_if_t<Dummy && std::is_default_constructible_v<Type>>>
- compressed_pair_element()
- : value{} {}
- template<typename Args, typename = std::enable_if_t<!std::is_same_v<std::remove_cv_t<std::remove_reference_t<Args>>, compressed_pair_element>>>
- compressed_pair_element(Args &&args)
- : value{std::forward<Args>(args)} {}
- template<typename... Args, std::size_t... Index>
- compressed_pair_element(std::tuple<Args...> args, std::index_sequence<Index...>)
- : value{std::forward<Args>(std::get<Index>(args))...} {}
- [[nodiscard]] reference get() ENTT_NOEXCEPT {
- return value;
- }
- [[nodiscard]] const_reference get() const ENTT_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<bool Dummy = true, typename = std::enable_if_t<Dummy && std::is_default_constructible_v<base_type>>>
- compressed_pair_element()
- : base_type{} {}
- template<typename Args, typename = std::enable_if_t<!std::is_same_v<std::remove_cv_t<std::remove_reference_t<Args>>, compressed_pair_element>>>
- compressed_pair_element(Args &&args)
- : base_type{std::forward<Args>(args)} {}
- template<typename... Args, std::size_t... Index>
- compressed_pair_element(std::tuple<Args...> args, std::index_sequence<Index...>)
- : base_type{std::forward<Args>(std::get<Index>(args))...} {}
- [[nodiscard]] reference get() ENTT_NOEXCEPT {
- return *this;
- }
- [[nodiscard]] const_reference get() const ENTT_NOEXCEPT {
- return *this;
- }
- };
- } // namespace internal
- /**
- * Internal details not to be documented.
- * @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()
- : 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) = 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)
- : 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)
- : first_base{std::move(args), std::index_sequence_for<Args...>{}},
- second_base{std::move(other), std::index_sequence_for<Other...>{}} {}
- /**
- * @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) = default;
- /**
- * @brief Returns the first element that a pair stores.
- * @return The first element that a pair stores.
- */
- [[nodiscard]] first_type &first() ENTT_NOEXCEPT {
- return static_cast<first_base &>(*this).get();
- }
- /*! @copydoc first */
- [[nodiscard]] const first_type &first() const ENTT_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]] second_type &second() ENTT_NOEXCEPT {
- return static_cast<second_base &>(*this).get();
- }
- /*! @copydoc second */
- [[nodiscard]] const second_type &second() const ENTT_NOEXCEPT {
- return static_cast<const second_base &>(*this).get();
- }
- /**
- * @brief Swaps two compressed pair objects.
- * @param other The compressed pair to swap with.
- */
- void swap(compressed_pair &other) {
- 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>
- decltype(auto) get() ENTT_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>
- decltype(auto) get() const ENTT_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>
- inline void swap(compressed_pair<First, Second> &lhs, compressed_pair<First, Second> &rhs) {
- lhs.swap(rhs);
- }
- } // namespace entt
- // disable structured binding support for clang 6, it messes when specializing tuple_size
- #if !defined __clang_major__ || __clang_major__ > 6
- 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
- #endif
- // #include "../core/iterator.hpp"
- #ifndef ENTT_CORE_ITERATOR_HPP
- #define ENTT_CORE_ITERATOR_HPP
- #include <iterator>
- #include <memory>
- #include <utility>
- // #include "../config/config.h"
- 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 Pointer type. */
- using pointer = Type *;
- /*! @brief Default copy constructor, deleted on purpose. */
- input_iterator_pointer(const input_iterator_pointer &) = delete;
- /*! @brief Default move constructor. */
- input_iterator_pointer(input_iterator_pointer &&) = default;
- /**
- * @brief Constructs a proxy object by move.
- * @param val Value to use to initialize the proxy object.
- */
- input_iterator_pointer(Type &&val)
- : value{std::move(val)} {}
- /**
- * @brief Default copy assignment operator, deleted on purpose.
- * @return This proxy object.
- */
- input_iterator_pointer &operator=(const input_iterator_pointer &) = delete;
- /**
- * @brief Default move assignment operator.
- * @return This proxy object.
- */
- input_iterator_pointer &operator=(input_iterator_pointer &&) = default;
- /**
- * @brief Access operator for accessing wrapped values.
- * @return A pointer to the wrapped value.
- */
- [[nodiscard]] pointer operator->() ENTT_NOEXCEPT {
- return std::addressof(value);
- }
- private:
- Type value;
- };
- /**
- * @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. */
- iterable_adaptor() = default;
- /**
- * @brief Creates an iterable object from a pair of iterators.
- * @param from Begin iterator.
- * @param to End iterator.
- */
- iterable_adaptor(iterator from, sentinel to)
- : first{from},
- last{to} {}
- /**
- * @brief Returns an iterator to the beginning.
- * @return An iterator to the first element of the range.
- */
- [[nodiscard]] iterator begin() const ENTT_NOEXCEPT {
- return first;
- }
- /**
- * @brief Returns an iterator to the end.
- * @return An iterator to the element following the last element of the
- * range.
- */
- [[nodiscard]] sentinel end() const ENTT_NOEXCEPT {
- return last;
- }
- /*! @copydoc begin */
- [[nodiscard]] iterator cbegin() const ENTT_NOEXCEPT {
- return begin();
- }
- /*! @copydoc end */
- [[nodiscard]] sentinel cend() const ENTT_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 <limits>
- #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) ENTT_NOEXCEPT {
- if constexpr(std::is_pointer_v<std::remove_cv_t<std::remove_reference_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) ENTT_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) ENTT_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) ENTT_NOEXCEPT {
- ENTT_ASSERT(std::allocator_traits<Allocator>::propagate_on_container_swap::value || lhs == rhs, "Cannot swap the containers");
- if constexpr(std::allocator_traits<Allocator>::propagate_on_container_swap::value) {
- using std::swap;
- swap(lhs, rhs);
- }
- }
- /**
- * @brief Checks whether a value is a power of two or not.
- * @param value A value that may or may not be a power of two.
- * @return True if the value is a power of two, false otherwise.
- */
- [[nodiscard]] inline constexpr bool is_power_of_two(const std::size_t value) ENTT_NOEXCEPT {
- return value && ((value & (value - 1)) == 0);
- }
- /**
- * @brief Computes the smallest power of two greater than or equal to a value.
- * @param value The value to use.
- * @return The smallest power of two greater than or equal to the given value.
- */
- [[nodiscard]] inline constexpr std::size_t next_power_of_two(const std::size_t value) ENTT_NOEXCEPT {
- ENTT_ASSERT(value < (std::size_t{1u} << (std::numeric_limits<std::size_t>::digits - 1)), "Numeric limits exceeded");
- std::size_t curr = value - (value != 0u);
- for(int next = 1; next < std::numeric_limits<std::size_t>::digits; next = next * 2) {
- curr |= curr >> next;
- }
- return ++curr;
- }
- /**
- * @brief Fast module utility function (powers of two only).
- * @param value A value for which to calculate the modulus.
- * @param mod _Modulus_, it must be a power of two.
- * @return The common remainder.
- */
- [[nodiscard]] inline constexpr std::size_t fast_mod(const std::size_t value, const std::size_t mod) ENTT_NOEXCEPT {
- ENTT_ASSERT(is_power_of_two(mod), "Value must be a power of two");
- return value & (mod - 1u);
- }
- /**
- * @brief Deleter for allocator-aware unique pointers (waiting for C++20).
- * @tparam Args Types of arguments to use to construct the object.
- */
- 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.
- */
- allocation_deleter(const allocator_type &alloc)
- : Allocator{alloc} {}
- /**
- * @brief Destroys the pointed object and deallocates its memory.
- * @param ptr A valid pointer to an object of the given type.
- */
- void operator()(pointer ptr) {
- using alloc_traits = typename 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>
- 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
- * Internal details not to be documented.
- */
- 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) ENTT_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) ENTT_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) ENTT_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) ENTT_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) ENTT_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) ENTT_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
- /**
- * Internal details not to be documented.
- * @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) ENTT_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([&](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 <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.
- * @tparam The size of the type if `sizeof` accepts it, 0 otherwise.
- */
- 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))>>
- : 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 Type First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<std::size_t Index, typename Type, typename... Other>
- struct type_list_element<Index, type_list<Type, Other...>>
- : type_list_element<Index - 1u, type_list<Other...>> {};
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam Type First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<typename Type, typename... Other>
- struct type_list_element<0u, type_list<Type, Other...>> {
- /*! @brief Searched type. */
- using type = Type;
- };
- /**
- * @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 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;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename>
- struct type_list_unique;
- /**
- * @brief Removes duplicates types from a type list.
- * @tparam Type One of the types provided by the given type list.
- * @tparam Other The other types provided by the given type list.
- */
- template<typename Type, typename... Other>
- struct type_list_unique<type_list<Type, Other...>> {
- /*! @brief A type list without duplicate types. */
- using type = std::conditional_t<
- (std::is_same_v<Type, Other> || ...),
- typename type_list_unique<type_list<Other...>>::type,
- type_list_cat_t<type_list<Type>, typename type_list_unique<type_list<Other...>>::type>>;
- };
- /*! @brief Removes duplicates types from a type list. */
- template<>
- struct type_list_unique<type_list<>> {
- /*! @brief A type list without duplicate types. */
- using type = type_list<>;
- };
- /**
- * @brief Helper type.
- * @tparam Type A type list.
- */
- template<typename Type>
- using type_list_unique_t = typename type_list_unique<Type>::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::disjunction<std::is_same<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 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 value. */
- static constexpr auto value = Value;
- };
- /**
- * @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 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 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
- * Internal details not to be documented.
- */
- 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
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /*! @copydoc is_iterator */
- template<typename Type>
- struct is_iterator<Type, std::enable_if_t<!std::is_same_v<std::remove_const_t<std::remove_pointer_t<Type>>, void>>>
- : 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::conjunction<std::is_empty<Type>, std::negation<std::is_final<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;
- /**
- * @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, typename = void>
- struct is_equality_comparable: std::false_type {};
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- 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 Type, std::size_t... Index>
- [[nodiscard]] constexpr bool unpack_maybe_equality_comparable(std::index_sequence<Index...>) {
- return (is_equality_comparable<std::tuple_element_t<Index, Type>>::value && ...);
- }
- template<typename>
- [[nodiscard]] constexpr bool maybe_equality_comparable(choice_t<0>) {
- return true;
- }
- template<typename Type>
- [[nodiscard]] constexpr auto maybe_equality_comparable(choice_t<1>) -> decltype(std::declval<typename Type::value_type>(), bool{}) {
- if constexpr(is_iterator_v<Type>) {
- return true;
- } else if constexpr(std::is_same_v<typename Type::value_type, Type>) {
- return maybe_equality_comparable<Type>(choice<0>);
- } else {
- return is_equality_comparable<typename Type::value_type>::value;
- }
- }
- template<typename Type>
- [[nodiscard]] constexpr std::enable_if_t<is_complete_v<std::tuple_size<std::remove_const_t<Type>>>, bool> maybe_equality_comparable(choice_t<2>) {
- if constexpr(has_tuple_size_value<Type>::value) {
- return unpack_maybe_equality_comparable<Type>(std::make_index_sequence<std::tuple_size<Type>::value>{});
- } else {
- return maybe_equality_comparable<Type>(choice<1>);
- }
- }
- } // namespace internal
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /*! @copydoc is_equality_comparable */
- template<typename Type>
- struct is_equality_comparable<Type, std::void_t<decltype(std::declval<Type>() == std::declval<Type>())>>
- : std::bool_constant<internal::maybe_equality_comparable<Type>(choice<2>)> {};
- /**
- * @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 = std::add_const_t<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;
- } // namespace entt
- #endif
- // #include "fwd.hpp"
- #ifndef ENTT_CONTAINER_FWD_HPP
- #define ENTT_CONTAINER_FWD_HPP
- #include <functional>
- #include <memory>
- namespace entt {
- template<
- typename Key,
- typename Type,
- typename = std::hash<Key>,
- typename = std::equal_to<Key>,
- typename = std::allocator<std::pair<const Key, Type>>>
- class dense_map;
- template<
- typename Type,
- typename = std::hash<Type>,
- typename = std::equal_to<Type>,
- typename = std::allocator<Type>>
- class dense_set;
- } // namespace entt
- #endif
- namespace entt {
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- namespace internal {
- 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;
- dense_map_iterator() ENTT_NOEXCEPT
- : it{} {}
- dense_map_iterator(const It iter) ENTT_NOEXCEPT
- : it{iter} {}
- template<typename Other, typename = std::enable_if_t<!std::is_same_v<It, Other> && std::is_constructible_v<It, Other>>>
- dense_map_iterator(const dense_map_iterator<Other> &other) ENTT_NOEXCEPT
- : it{other.it} {}
- dense_map_iterator &operator++() ENTT_NOEXCEPT {
- return ++it, *this;
- }
- dense_map_iterator operator++(int) ENTT_NOEXCEPT {
- dense_map_iterator orig = *this;
- return ++(*this), orig;
- }
- dense_map_iterator &operator--() ENTT_NOEXCEPT {
- return --it, *this;
- }
- dense_map_iterator operator--(int) ENTT_NOEXCEPT {
- dense_map_iterator orig = *this;
- return operator--(), orig;
- }
- dense_map_iterator &operator+=(const difference_type value) ENTT_NOEXCEPT {
- it += value;
- return *this;
- }
- dense_map_iterator operator+(const difference_type value) const ENTT_NOEXCEPT {
- dense_map_iterator copy = *this;
- return (copy += value);
- }
- dense_map_iterator &operator-=(const difference_type value) ENTT_NOEXCEPT {
- return (*this += -value);
- }
- dense_map_iterator operator-(const difference_type value) const ENTT_NOEXCEPT {
- return (*this + -value);
- }
- [[nodiscard]] reference operator[](const difference_type value) const ENTT_NOEXCEPT {
- return {it[value].element.first, it[value].element.second};
- }
- [[nodiscard]] pointer operator->() const ENTT_NOEXCEPT {
- return operator*();
- }
- [[nodiscard]] reference operator*() const ENTT_NOEXCEPT {
- return {it->element.first, it->element.second};
- }
- template<typename ILhs, typename IRhs>
- friend std::ptrdiff_t operator-(const dense_map_iterator<ILhs> &, const dense_map_iterator<IRhs> &) ENTT_NOEXCEPT;
- template<typename ILhs, typename IRhs>
- friend bool operator==(const dense_map_iterator<ILhs> &, const dense_map_iterator<IRhs> &) ENTT_NOEXCEPT;
- template<typename ILhs, typename IRhs>
- friend bool operator<(const dense_map_iterator<ILhs> &, const dense_map_iterator<IRhs> &) ENTT_NOEXCEPT;
- private:
- It it;
- };
- template<typename ILhs, typename IRhs>
- [[nodiscard]] std::ptrdiff_t operator-(const dense_map_iterator<ILhs> &lhs, const dense_map_iterator<IRhs> &rhs) ENTT_NOEXCEPT {
- return lhs.it - rhs.it;
- }
- template<typename ILhs, typename IRhs>
- [[nodiscard]] bool operator==(const dense_map_iterator<ILhs> &lhs, const dense_map_iterator<IRhs> &rhs) ENTT_NOEXCEPT {
- return lhs.it == rhs.it;
- }
- template<typename ILhs, typename IRhs>
- [[nodiscard]] bool operator!=(const dense_map_iterator<ILhs> &lhs, const dense_map_iterator<IRhs> &rhs) ENTT_NOEXCEPT {
- return !(lhs == rhs);
- }
- template<typename ILhs, typename IRhs>
- [[nodiscard]] bool operator<(const dense_map_iterator<ILhs> &lhs, const dense_map_iterator<IRhs> &rhs) ENTT_NOEXCEPT {
- return lhs.it < rhs.it;
- }
- template<typename ILhs, typename IRhs>
- [[nodiscard]] bool operator>(const dense_map_iterator<ILhs> &lhs, const dense_map_iterator<IRhs> &rhs) ENTT_NOEXCEPT {
- return rhs < lhs;
- }
- template<typename ILhs, typename IRhs>
- [[nodiscard]] bool operator<=(const dense_map_iterator<ILhs> &lhs, const dense_map_iterator<IRhs> &rhs) ENTT_NOEXCEPT {
- return !(lhs > rhs);
- }
- template<typename ILhs, typename IRhs>
- [[nodiscard]] bool operator>=(const dense_map_iterator<ILhs> &lhs, const dense_map_iterator<IRhs> &rhs) ENTT_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;
- dense_map_local_iterator() ENTT_NOEXCEPT
- : it{},
- offset{} {}
- dense_map_local_iterator(It iter, const std::size_t pos) ENTT_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>>>
- dense_map_local_iterator(const dense_map_local_iterator<Other> &other) ENTT_NOEXCEPT
- : it{other.it},
- offset{other.offset} {}
- dense_map_local_iterator &operator++() ENTT_NOEXCEPT {
- return offset = it[offset].next, *this;
- }
- dense_map_local_iterator operator++(int) ENTT_NOEXCEPT {
- dense_map_local_iterator orig = *this;
- return ++(*this), orig;
- }
- [[nodiscard]] pointer operator->() const ENTT_NOEXCEPT {
- return operator*();
- }
- [[nodiscard]] reference operator*() const ENTT_NOEXCEPT {
- return {it[offset].element.first, it[offset].element.second};
- }
- [[nodiscard]] std::size_t index() const ENTT_NOEXCEPT {
- return offset;
- }
- private:
- It it;
- std::size_t offset;
- };
- template<typename ILhs, typename IRhs>
- [[nodiscard]] bool operator==(const dense_map_local_iterator<ILhs> &lhs, const dense_map_local_iterator<IRhs> &rhs) ENTT_NOEXCEPT {
- return lhs.index() == rhs.index();
- }
- template<typename ILhs, typename IRhs>
- [[nodiscard]] bool operator!=(const dense_map_local_iterator<ILhs> &lhs, const dense_map_local_iterator<IRhs> &rhs) ENTT_NOEXCEPT {
- return !(lhs == rhs);
- }
- } // namespace internal
- /**
- * Internal details not to be documented.
- * @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;
- using node_type = internal::dense_map_node<Key, Type>;
- using alloc_traits = typename 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 ENTT_NOEXCEPT {
- return fast_mod(sparse.second()(key), bucket_count());
- }
- template<typename Other>
- [[nodiscard]] auto constrained_find(const Other &key, std::size_t bucket) {
- for(auto it = begin(bucket), last = end(bucket); it != last; ++it) {
- if(packed.second()(it->first, key)) {
- return begin() + static_cast<typename iterator::difference_type>(it.index());
- }
- }
- return end();
- }
- template<typename Other>
- [[nodiscard]] auto constrained_find(const Other &key, std::size_t bucket) const {
- for(auto it = cbegin(bucket), last = cend(bucket); it != last; ++it) {
- if(packed.second()(it->first, key)) {
- return cbegin() + static_cast<typename iterator::difference_type>(it.index());
- }
- }
- 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) {
- packed.first()[pos] = std::move(packed.first().back());
- size_type *curr = sparse.first().data() + key_to_bucket(packed.first().back().element.first);
- for(; *curr != last; curr = &packed.first()[*curr].next) {}
- *curr = pos;
- }
- packed.first().pop_back();
- }
- void rehash_if_required() {
- if(size() > (bucket_count() * max_load_factor())) {
- rehash(bucket_count() * 2u);
- }
- }
- public:
- /*! @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 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 Allocator type. */
- using allocator_type = Allocator;
- /*! @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 bucket_count Minimal number of buckets.
- * @param allocator The allocator to use.
- */
- dense_map(const size_type bucket_count, const allocator_type &allocator)
- : dense_map{bucket_count, hasher{}, key_equal{}, allocator} {}
- /**
- * @brief Constructs an empty container with a given allocator, hash
- * function and user supplied minimal number of buckets.
- * @param bucket_count Minimal number of buckets.
- * @param hash Hash function to use.
- * @param allocator The allocator to use.
- */
- dense_map(const size_type bucket_count, const hasher &hash, const allocator_type &allocator)
- : dense_map{bucket_count, 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 bucket_count 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 bucket_count, const hasher &hash = hasher{}, const key_equal &equal = key_equal{}, const allocator_type &allocator = allocator_type{})
- : sparse{allocator, hash},
- packed{allocator, equal},
- threshold{default_threshold} {
- rehash(bucket_count);
- }
- /*! @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 &&) = 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 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 &&) = default;
- /**
- * @brief Returns the associated allocator.
- * @return The associated allocator.
- */
- [[nodiscard]] constexpr allocator_type get_allocator() const ENTT_NOEXCEPT {
- return sparse.first().get_allocator();
- }
- /**
- * @brief Returns an iterator to the beginning.
- *
- * The returned iterator points to the first instance of the internal array.
- * 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 ENTT_NOEXCEPT {
- return packed.first().begin();
- }
- /*! @copydoc cbegin */
- [[nodiscard]] const_iterator begin() const ENTT_NOEXCEPT {
- return cbegin();
- }
- /*! @copydoc begin */
- [[nodiscard]] iterator begin() ENTT_NOEXCEPT {
- return packed.first().begin();
- }
- /**
- * @brief Returns an iterator to the end.
- *
- * The returned iterator points to the element following the last instance
- * of the internal array. Attempting to dereference the returned iterator
- * results in undefined behavior.
- *
- * @return An iterator to the element following the last instance of the
- * internal array.
- */
- [[nodiscard]] const_iterator cend() const ENTT_NOEXCEPT {
- return packed.first().end();
- }
- /*! @copydoc cend */
- [[nodiscard]] const_iterator end() const ENTT_NOEXCEPT {
- return cend();
- }
- /*! @copydoc end */
- [[nodiscard]] iterator end() ENTT_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 ENTT_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 ENTT_NOEXCEPT {
- return packed.first().size();
- }
- /*! @brief Clears the container. */
- void clear() ENTT_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()[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().data() + key_to_bucket(key); *curr != (std::numeric_limits<size_type>::max)(); 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 Exchanges the contents with those of a given container.
- * @param other Container to exchange the content with.
- */
- void swap(dense_map &other) {
- using std::swap;
- swap(sparse, other.sparse);
- swap(packed, other.packed);
- swap(threshold, other.threshold);
- }
- /**
- * @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 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 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
- * 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 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 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 {packed.first().begin(), (std::numeric_limits<size_type>::max)()};
- }
- /**
- * @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([[maybe_unused]] 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 {packed.first().begin(), (std::numeric_limits<size_type>::max)()};
- }
- /**
- * @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 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 count New number of buckets.
- */
- void rehash(const size_type count) {
- auto value = (std::max)(count, minimum_capacity);
- value = (std::max)(value, static_cast<size_type>(size() / max_load_factor()));
- if(const auto sz = next_power_of_two(value); sz != bucket_count()) {
- sparse.first().resize(sz);
- std::fill(sparse.first().begin(), sparse.first().end(), (std::numeric_limits<size_type>::max)());
- 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 count New number of elements.
- */
- void reserve(const size_type count) {
- packed.first().reserve(count);
- rehash(static_cast<size_type>(std::ceil(count / 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;
- };
- } // namespace entt
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- 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
- /**
- * Internal details not to be documented.
- * @endcond
- */
- #endif
- // #include "container/dense_set.hpp"
- #ifndef ENTT_CONTAINER_DENSE_SET_HPP
- #define ENTT_CONTAINER_DENSE_SET_HPP
- #include <algorithm>
- #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/compressed_pair.hpp"
- // #include "../core/memory.hpp"
- // #include "../core/type_traits.hpp"
- // #include "fwd.hpp"
- namespace entt {
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- namespace internal {
- 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;
- dense_set_iterator() ENTT_NOEXCEPT
- : it{} {}
- dense_set_iterator(const It iter) ENTT_NOEXCEPT
- : it{iter} {}
- template<typename Other, typename = std::enable_if_t<!std::is_same_v<It, Other> && std::is_constructible_v<It, Other>>>
- dense_set_iterator(const dense_set_iterator<Other> &other) ENTT_NOEXCEPT
- : it{other.it} {}
- dense_set_iterator &operator++() ENTT_NOEXCEPT {
- return ++it, *this;
- }
- dense_set_iterator operator++(int) ENTT_NOEXCEPT {
- dense_set_iterator orig = *this;
- return ++(*this), orig;
- }
- dense_set_iterator &operator--() ENTT_NOEXCEPT {
- return --it, *this;
- }
- dense_set_iterator operator--(int) ENTT_NOEXCEPT {
- dense_set_iterator orig = *this;
- return operator--(), orig;
- }
- dense_set_iterator &operator+=(const difference_type value) ENTT_NOEXCEPT {
- it += value;
- return *this;
- }
- dense_set_iterator operator+(const difference_type value) const ENTT_NOEXCEPT {
- dense_set_iterator copy = *this;
- return (copy += value);
- }
- dense_set_iterator &operator-=(const difference_type value) ENTT_NOEXCEPT {
- return (*this += -value);
- }
- dense_set_iterator operator-(const difference_type value) const ENTT_NOEXCEPT {
- return (*this + -value);
- }
- [[nodiscard]] reference operator[](const difference_type value) const ENTT_NOEXCEPT {
- return it[value].second;
- }
- [[nodiscard]] pointer operator->() const ENTT_NOEXCEPT {
- return std::addressof(it->second);
- }
- [[nodiscard]] reference operator*() const ENTT_NOEXCEPT {
- return *operator->();
- }
- template<typename ILhs, typename IRhs>
- friend std::ptrdiff_t operator-(const dense_set_iterator<ILhs> &, const dense_set_iterator<IRhs> &) ENTT_NOEXCEPT;
- template<typename ILhs, typename IRhs>
- friend bool operator==(const dense_set_iterator<ILhs> &, const dense_set_iterator<IRhs> &) ENTT_NOEXCEPT;
- template<typename ILhs, typename IRhs>
- friend bool operator<(const dense_set_iterator<ILhs> &, const dense_set_iterator<IRhs> &) ENTT_NOEXCEPT;
- private:
- It it;
- };
- template<typename ILhs, typename IRhs>
- [[nodiscard]] std::ptrdiff_t operator-(const dense_set_iterator<ILhs> &lhs, const dense_set_iterator<IRhs> &rhs) ENTT_NOEXCEPT {
- return lhs.it - rhs.it;
- }
- template<typename ILhs, typename IRhs>
- [[nodiscard]] bool operator==(const dense_set_iterator<ILhs> &lhs, const dense_set_iterator<IRhs> &rhs) ENTT_NOEXCEPT {
- return lhs.it == rhs.it;
- }
- template<typename ILhs, typename IRhs>
- [[nodiscard]] bool operator!=(const dense_set_iterator<ILhs> &lhs, const dense_set_iterator<IRhs> &rhs) ENTT_NOEXCEPT {
- return !(lhs == rhs);
- }
- template<typename ILhs, typename IRhs>
- [[nodiscard]] bool operator<(const dense_set_iterator<ILhs> &lhs, const dense_set_iterator<IRhs> &rhs) ENTT_NOEXCEPT {
- return lhs.it < rhs.it;
- }
- template<typename ILhs, typename IRhs>
- [[nodiscard]] bool operator>(const dense_set_iterator<ILhs> &lhs, const dense_set_iterator<IRhs> &rhs) ENTT_NOEXCEPT {
- return rhs < lhs;
- }
- template<typename ILhs, typename IRhs>
- [[nodiscard]] bool operator<=(const dense_set_iterator<ILhs> &lhs, const dense_set_iterator<IRhs> &rhs) ENTT_NOEXCEPT {
- return !(lhs > rhs);
- }
- template<typename ILhs, typename IRhs>
- [[nodiscard]] bool operator>=(const dense_set_iterator<ILhs> &lhs, const dense_set_iterator<IRhs> &rhs) ENTT_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;
- dense_set_local_iterator() ENTT_NOEXCEPT
- : it{},
- offset{} {}
- dense_set_local_iterator(It iter, const std::size_t pos) ENTT_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>>>
- dense_set_local_iterator(const dense_set_local_iterator<Other> &other) ENTT_NOEXCEPT
- : it{other.it},
- offset{other.offset} {}
- dense_set_local_iterator &operator++() ENTT_NOEXCEPT {
- return offset = it[offset].first, *this;
- }
- dense_set_local_iterator operator++(int) ENTT_NOEXCEPT {
- dense_set_local_iterator orig = *this;
- return ++(*this), orig;
- }
- [[nodiscard]] pointer operator->() const ENTT_NOEXCEPT {
- return std::addressof(it[offset].second);
- }
- [[nodiscard]] reference operator*() const ENTT_NOEXCEPT {
- return *operator->();
- }
- [[nodiscard]] std::size_t index() const ENTT_NOEXCEPT {
- return offset;
- }
- private:
- It it;
- std::size_t offset;
- };
- template<typename ILhs, typename IRhs>
- [[nodiscard]] bool operator==(const dense_set_local_iterator<ILhs> &lhs, const dense_set_local_iterator<IRhs> &rhs) ENTT_NOEXCEPT {
- return lhs.index() == rhs.index();
- }
- template<typename ILhs, typename IRhs>
- [[nodiscard]] bool operator!=(const dense_set_local_iterator<ILhs> &lhs, const dense_set_local_iterator<IRhs> &rhs) ENTT_NOEXCEPT {
- return !(lhs == rhs);
- }
- } // namespace internal
- /**
- * Internal details not to be documented.
- * @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;
- 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 ENTT_NOEXCEPT {
- return fast_mod(sparse.second()(value), bucket_count());
- }
- template<typename Other>
- [[nodiscard]] auto constrained_find(const Other &value, std::size_t bucket) {
- for(auto it = begin(bucket), last = end(bucket); it != last; ++it) {
- if(packed.second()(*it, value)) {
- return begin() + static_cast<typename iterator::difference_type>(it.index());
- }
- }
- return end();
- }
- template<typename Other>
- [[nodiscard]] auto constrained_find(const Other &value, std::size_t bucket) const {
- for(auto it = cbegin(bucket), last = cend(bucket); it != last; ++it) {
- if(packed.second()(*it, value)) {
- return cbegin() + static_cast<typename iterator::difference_type>(it.index());
- }
- }
- 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) {
- packed.first()[pos] = std::move(packed.first().back());
- size_type *curr = sparse.first().data() + value_to_bucket(packed.first().back().second);
- for(; *curr != last; curr = &packed.first()[*curr].first) {}
- *curr = pos;
- }
- packed.first().pop_back();
- }
- void rehash_if_required() {
- if(size() > (bucket_count() * max_load_factor())) {
- rehash(bucket_count() * 2u);
- }
- }
- public:
- /*! @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 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 Allocator type. */
- using allocator_type = Allocator;
- /*! @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 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 bucket_count Minimal number of buckets.
- * @param allocator The allocator to use.
- */
- dense_set(const size_type bucket_count, const allocator_type &allocator)
- : dense_set{bucket_count, hasher{}, key_equal{}, allocator} {}
- /**
- * @brief Constructs an empty container with a given allocator, hash
- * function and user supplied minimal number of buckets.
- * @param bucket_count Minimal number of buckets.
- * @param hash Hash function to use.
- * @param allocator The allocator to use.
- */
- dense_set(const size_type bucket_count, const hasher &hash, const allocator_type &allocator)
- : dense_set{bucket_count, 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 bucket_count 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 bucket_count, const hasher &hash = hasher{}, const key_equal &equal = key_equal{}, const allocator_type &allocator = allocator_type{})
- : sparse{allocator, hash},
- packed{allocator, equal},
- threshold{default_threshold} {
- rehash(bucket_count);
- }
- /*! @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 &&) = 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 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 &&) = default;
- /**
- * @brief Returns the associated allocator.
- * @return The associated allocator.
- */
- [[nodiscard]] constexpr allocator_type get_allocator() const ENTT_NOEXCEPT {
- return sparse.first().get_allocator();
- }
- /**
- * @brief Returns an iterator to the beginning.
- *
- * The returned iterator points to the first instance of the internal array.
- * 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 ENTT_NOEXCEPT {
- return packed.first().begin();
- }
- /*! @copydoc cbegin */
- [[nodiscard]] const_iterator begin() const ENTT_NOEXCEPT {
- return cbegin();
- }
- /*! @copydoc begin */
- [[nodiscard]] iterator begin() ENTT_NOEXCEPT {
- return packed.first().begin();
- }
- /**
- * @brief Returns an iterator to the end.
- *
- * The returned iterator points to the element following the last instance
- * of the internal array. Attempting to dereference the returned iterator
- * results in undefined behavior.
- *
- * @return An iterator to the element following the last instance of the
- * internal array.
- */
- [[nodiscard]] const_iterator cend() const ENTT_NOEXCEPT {
- return packed.first().end();
- }
- /*! @copydoc cend */
- [[nodiscard]] const_iterator end() const ENTT_NOEXCEPT {
- return cend();
- }
- /*! @copydoc end */
- [[nodiscard]] iterator end() ENTT_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 ENTT_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 ENTT_NOEXCEPT {
- return packed.first().size();
- }
- /*! @brief Clears the container. */
- void clear() ENTT_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::remove_cv_t<std::remove_reference_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()[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().data() + value_to_bucket(value); *curr != (std::numeric_limits<size_type>::max)(); 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 Exchanges the contents with those of a given container.
- * @param other Container to exchange the content with.
- */
- void swap(dense_set &other) {
- using std::swap;
- swap(sparse, other.sparse);
- swap(packed, other.packed);
- swap(threshold, other.threshold);
- }
- /**
- * @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 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 {packed.first().begin(), (std::numeric_limits<size_type>::max)()};
- }
- /**
- * @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([[maybe_unused]] 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 {packed.first().begin(), (std::numeric_limits<size_type>::max)()};
- }
- /**
- * @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 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 count New number of buckets.
- */
- void rehash(const size_type count) {
- auto value = (std::max)(count, minimum_capacity);
- value = (std::max)(value, static_cast<size_type>(size() / max_load_factor()));
- if(const auto sz = next_power_of_two(value); sz != bucket_count()) {
- sparse.first().resize(sz);
- std::fill(sparse.first().begin(), sparse.first().end(), (std::numeric_limits<size_type>::max)());
- 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 count New number of elements.
- */
- void reserve(const size_type count) {
- packed.first().reserve(count);
- rehash(static_cast<size_type>(std::ceil(count / 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;
- };
- } // namespace entt
- #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 <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
- #define ENTT_STR(arg) #arg
- #define ENTT_XSTR(arg) ENTT_STR(arg)
- #endif
- #define ENTT_VERSION_MAJOR 3
- #define ENTT_VERSION_MINOR 10
- #define ENTT_VERSION_PATCH 3
- #define ENTT_VERSION \
- ENTT_XSTR(ENTT_VERSION_MAJOR) \
- "." ENTT_XSTR(ENTT_VERSION_MINOR) "." ENTT_XSTR(ENTT_VERSION_PATCH)
- #endif
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #ifndef ENTT_NOEXCEPT
- # define ENTT_NOEXCEPT noexcept
- # define ENTT_NOEXCEPT_IF(expr) noexcept(expr)
- # else
- # define ENTT_NOEXCEPT_IF(...)
- #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
- #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(...) (void(0))
- #elif !defined ENTT_ASSERT
- # include <cassert>
- # define ENTT_ASSERT(condition, ...) assert(condition)
- #endif
- #ifdef ENTT_NO_ETO
- # define ENTT_IGNORE_IF_EMPTY false
- #else
- # define ENTT_IGNORE_IF_EMPTY true
- #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
- #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
- #endif
- 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<class Type>
- [[nodiscard]] constexpr Type &&operator()(Type &&value) const ENTT_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) ENTT_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) ENTT_NOEXCEPT {
- return func;
- }
- /**
- * @brief Helper type for visitors.
- * @tparam Func Types of function objects.
- */
- template<class... Func>
- struct overloaded: Func... {
- using Func::operator()...;
- };
- /**
- * @brief Deduction guide.
- * @tparam Func Types of function objects.
- */
- template<class... Func>
- overloaded(Func...) -> overloaded<Func...>;
- /**
- * @brief Basic implementation of a y-combinator.
- * @tparam Func Type of a potentially recursive function.
- */
- template<class Func>
- struct y_combinator {
- /**
- * @brief Constructs a y-combinator from a given function.
- * @param recursive A potentially recursive function.
- */
- y_combinator(Func recursive)
- : 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<class... Args>
- decltype(auto) operator()(Args &&...args) const {
- return func(*this, std::forward<Args>(args)...);
- }
- /*! @copydoc operator()() */
- template<class... Args>
- decltype(auto) operator()(Args &&...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;
- for(; pre > first && compare(value, *(pre - 1)); --pre) {
- *pre = std::move(*(pre - 1));
- }
- *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) {
- static constexpr auto mask = (1 << Bit) - 1;
- static constexpr auto buckets = 1 << Bit;
- static constexpr auto passes = N / Bit;
- using value_type = typename std::iterator_traits<It>::value_type;
- std::vector<value_type> aux(std::distance(first, last));
- auto part = [getter = std::move(getter)](auto from, auto to, auto out, auto start) {
- std::size_t index[buckets]{};
- std::size_t count[buckets]{};
- for(auto it = from; it != to; ++it) {
- ++count[(getter(*it) >> start) & mask];
- }
- 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) {
- out[index[(getter(*it) >> start) & mask]++] = std::move(*it);
- }
- };
- for(std::size_t pass = 0; pass < (passes & ~1); 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"
- // #include "../core/utility.hpp"
- #ifndef ENTT_CORE_UTILITY_HPP
- #define ENTT_CORE_UTILITY_HPP
- #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
- #define ENTT_STR(arg) #arg
- #define ENTT_XSTR(arg) ENTT_STR(arg)
- #endif
- #define ENTT_VERSION_MAJOR 3
- #define ENTT_VERSION_MINOR 10
- #define ENTT_VERSION_PATCH 3
- #define ENTT_VERSION \
- ENTT_XSTR(ENTT_VERSION_MAJOR) \
- "." ENTT_XSTR(ENTT_VERSION_MINOR) "." ENTT_XSTR(ENTT_VERSION_PATCH)
- #endif
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #ifndef ENTT_NOEXCEPT
- # define ENTT_NOEXCEPT noexcept
- # define ENTT_NOEXCEPT_IF(expr) noexcept(expr)
- # else
- # define ENTT_NOEXCEPT_IF(...)
- #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
- #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(...) (void(0))
- #elif !defined ENTT_ASSERT
- # include <cassert>
- # define ENTT_ASSERT(condition, ...) assert(condition)
- #endif
- #ifdef ENTT_NO_ETO
- # define ENTT_IGNORE_IF_EMPTY false
- #else
- # define ENTT_IGNORE_IF_EMPTY true
- #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
- #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
- #endif
- 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<class Type>
- [[nodiscard]] constexpr Type &&operator()(Type &&value) const ENTT_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) ENTT_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) ENTT_NOEXCEPT {
- return func;
- }
- /**
- * @brief Helper type for visitors.
- * @tparam Func Types of function objects.
- */
- template<class... Func>
- struct overloaded: Func... {
- using Func::operator()...;
- };
- /**
- * @brief Deduction guide.
- * @tparam Func Types of function objects.
- */
- template<class... Func>
- overloaded(Func...) -> overloaded<Func...>;
- /**
- * @brief Basic implementation of a y-combinator.
- * @tparam Func Type of a potentially recursive function.
- */
- template<class Func>
- struct y_combinator {
- /**
- * @brief Constructs a y-combinator from a given function.
- * @param recursive A potentially recursive function.
- */
- y_combinator(Func recursive)
- : 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<class... Args>
- decltype(auto) operator()(Args &&...args) const {
- return func(*this, std::forward<Args>(args)...);
- }
- /*! @copydoc operator()() */
- template<class... Args>
- decltype(auto) operator()(Args &&...args) {
- return func(*this, std::forward<Args>(args)...);
- }
- private:
- Func func;
- };
- } // namespace entt
- #endif
- // #include "fwd.hpp"
- #ifndef ENTT_CORE_FWD_HPP
- #define ENTT_CORE_FWD_HPP
- #include <cstdint>
- #include <type_traits>
- // #include "../config/config.h"
- namespace entt {
- template<std::size_t Len = sizeof(double[2]), std::size_t = alignof(typename std::aligned_storage_t<Len + !Len>)>
- 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<>;
- } // 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 "../core/attribute.h"
- #ifndef ENTT_CORE_ATTRIBUTE_H
- #define ENTT_CORE_ATTRIBUTE_H
- #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
- #endif
- // #include "fwd.hpp"
- // #include "hashed_string.hpp"
- #ifndef ENTT_CORE_HASHED_STRING_HPP
- #define ENTT_CORE_HASHED_STRING_HPP
- #include <cstddef>
- #include <cstdint>
- // #include "../config/config.h"
- // #include "fwd.hpp"
- namespace entt {
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- namespace internal {
- template<typename>
- struct fnv1a_traits;
- template<>
- struct fnv1a_traits<std::uint32_t> {
- using type = std::uint32_t;
- static constexpr std::uint32_t offset = 2166136261;
- static constexpr std::uint32_t prime = 16777619;
- };
- template<>
- struct fnv1a_traits<std::uint64_t> {
- using type = std::uint64_t;
- static constexpr std::uint64_t offset = 14695981039346656037ull;
- static constexpr std::uint64_t 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;
- size_type length;
- hash_type hash;
- };
- } // namespace internal
- /**
- * Internal details not to be documented.
- * @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 hs_traits = internal::fnv1a_traits<id_type>;
- struct const_wrapper {
- // non-explicit constructor on purpose
- constexpr const_wrapper(const Char *str) ENTT_NOEXCEPT: repr{str} {}
- const Char *repr;
- };
- // Fowler–Noll–Vo hash function v. 1a - the good
- [[nodiscard]] static constexpr auto helper(const Char *str) ENTT_NOEXCEPT {
- base_type base{str, 0u, hs_traits::offset};
- for(; str[base.length]; ++base.length) {
- base.hash = (base.hash ^ static_cast<hs_traits::type>(str[base.length])) * hs_traits::prime;
- }
- return base;
- }
- // Fowler–Noll–Vo hash function v. 1a - the good
- [[nodiscard]] static constexpr auto helper(const Char *str, const std::size_t len) ENTT_NOEXCEPT {
- base_type base{str, len, hs_traits::offset};
- for(size_type pos{}; pos < len; ++pos) {
- base.hash = (base.hash ^ static_cast<hs_traits::type>(str[pos])) * hs_traits::prime;
- }
- return base;
- }
- 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) ENTT_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>
- [[nodiscard]] static constexpr hash_type value(const value_type (&str)[N]) ENTT_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) ENTT_NOEXCEPT {
- return basic_hashed_string{wrapper};
- }
- /*! @brief Constructs an empty hashed string. */
- constexpr basic_hashed_string() ENTT_NOEXCEPT
- : base_type{} {}
- /**
- * @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) ENTT_NOEXCEPT
- : base_type{helper(str, len)} {}
- /**
- * @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>
- constexpr basic_hashed_string(const value_type (&str)[N]) ENTT_NOEXCEPT
- : base_type{helper(str)} {}
- /**
- * @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) ENTT_NOEXCEPT
- : base_type{helper(wrapper.repr)} {}
- /**
- * @brief Returns the size a hashed string.
- * @return The size of the hashed string.
- */
- [[nodiscard]] constexpr size_type size() const ENTT_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 ENTT_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 ENTT_NOEXCEPT {
- return base_type::hash;
- }
- /*! @copydoc data */
- [[nodiscard]] constexpr operator const value_type *() const ENTT_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 ENTT_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, const 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>
- 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) ENTT_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) ENTT_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) ENTT_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) ENTT_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) ENTT_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) ENTT_NOEXCEPT {
- return !(lhs < rhs);
- }
- /*! @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>;
- inline namespace literals {
- /**
- * @brief User defined literal for hashed strings.
- * @param str The literal without its suffix.
- * @return A properly initialized hashed string.
- */
- [[nodiscard]] constexpr hashed_string operator"" _hs(const char *str, std::size_t) ENTT_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]] constexpr hashed_wstring operator"" _hws(const wchar_t *str, std::size_t) ENTT_NOEXCEPT {
- return hashed_wstring{str};
- }
- } // namespace literals
- } // namespace entt
- #endif
- namespace entt {
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- namespace internal {
- struct ENTT_API type_index final {
- [[nodiscard]] static id_type next() ENTT_NOEXCEPT {
- static ENTT_MAYBE_ATOMIC(id_type) value{};
- return value++;
- }
- };
- template<typename Type>
- [[nodiscard]] constexpr auto stripped_type_name() ENTT_NOEXCEPT {
- #if defined ENTT_PRETTY_FUNCTION
- std::string_view pretty_function{ENTT_PRETTY_FUNCTION};
- auto first = pretty_function.find_first_not_of(' ', pretty_function.find_first_of(ENTT_PRETTY_FUNCTION_PREFIX) + 1);
- auto value = pretty_function.substr(first, pretty_function.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]] static constexpr std::string_view type_name(int) ENTT_NOEXCEPT {
- constexpr auto value = stripped_type_name<Type>();
- return value;
- }
- template<typename Type>
- [[nodiscard]] static std::string_view type_name(char) ENTT_NOEXCEPT {
- static const auto value = stripped_type_name<Type>();
- return value;
- }
- template<typename Type, auto = stripped_type_name<Type>().find_first_of('.')>
- [[nodiscard]] static constexpr id_type type_hash(int) ENTT_NOEXCEPT {
- constexpr auto stripped = stripped_type_name<Type>();
- constexpr auto value = hashed_string::value(stripped.data(), stripped.size());
- return value;
- }
- template<typename Type>
- [[nodiscard]] static id_type type_hash(char) ENTT_NOEXCEPT {
- static const auto value = [](const auto stripped) {
- return hashed_string::value(stripped.data(), stripped.size());
- }(stripped_type_name<Type>());
- return value;
- }
- } // namespace internal
- /**
- * Internal details not to be documented.
- * @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() ENTT_NOEXCEPT {
- static const id_type value = internal::type_index::next();
- return value;
- }
- /*! @copydoc value */
- [[nodiscard]] constexpr operator id_type() const ENTT_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() ENTT_NOEXCEPT {
- return internal::type_hash<Type>(0);
- #else
- [[nodiscard]] static constexpr id_type value() ENTT_NOEXCEPT {
- return type_index<Type>::value();
- #endif
- }
- /*! @copydoc value */
- [[nodiscard]] constexpr operator id_type() const ENTT_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() ENTT_NOEXCEPT {
- return internal::type_name<Type>(0);
- }
- /*! @copydoc value */
- [[nodiscard]] constexpr operator std::string_view() const ENTT_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>
- constexpr type_info(std::in_place_type_t<Type>) ENTT_NOEXCEPT
- : seq{type_index<std::remove_cv_t<std::remove_reference_t<Type>>>::value()},
- identifier{type_hash<std::remove_cv_t<std::remove_reference_t<Type>>>::value()},
- alias{type_name<std::remove_cv_t<std::remove_reference_t<Type>>>::value()} {}
- /**
- * @brief Type index.
- * @return Type index.
- */
- [[nodiscard]] constexpr id_type index() const ENTT_NOEXCEPT {
- return seq;
- }
- /**
- * @brief Type hash.
- * @return Type hash.
- */
- [[nodiscard]] constexpr id_type hash() const ENTT_NOEXCEPT {
- return identifier;
- }
- /**
- * @brief Type name.
- * @return Type name.
- */
- [[nodiscard]] constexpr std::string_view name() const ENTT_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]] inline constexpr bool operator==(const type_info &lhs, const type_info &rhs) ENTT_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]] inline constexpr bool operator!=(const type_info &lhs, const type_info &rhs) ENTT_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) ENTT_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) ENTT_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) ENTT_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) ENTT_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() ENTT_NOEXCEPT {
- if constexpr(std::is_same_v<Type, std::remove_cv_t<std::remove_reference_t<Type>>>) {
- static type_info instance{std::in_place_type<Type>};
- return instance;
- } else {
- return type_id<std::remove_cv_t<std::remove_reference_t<Type>>>();
- }
- }
- /*! @copydoc type_id */
- template<typename Type>
- [[nodiscard]] const type_info &type_id(Type &&) ENTT_NOEXCEPT {
- return type_id<std::remove_cv_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 <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.
- * @tparam The size of the type if `sizeof` accepts it, 0 otherwise.
- */
- 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))>>
- : 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 Type First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<std::size_t Index, typename Type, typename... Other>
- struct type_list_element<Index, type_list<Type, Other...>>
- : type_list_element<Index - 1u, type_list<Other...>> {};
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam Type First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<typename Type, typename... Other>
- struct type_list_element<0u, type_list<Type, Other...>> {
- /*! @brief Searched type. */
- using type = Type;
- };
- /**
- * @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 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;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename>
- struct type_list_unique;
- /**
- * @brief Removes duplicates types from a type list.
- * @tparam Type One of the types provided by the given type list.
- * @tparam Other The other types provided by the given type list.
- */
- template<typename Type, typename... Other>
- struct type_list_unique<type_list<Type, Other...>> {
- /*! @brief A type list without duplicate types. */
- using type = std::conditional_t<
- (std::is_same_v<Type, Other> || ...),
- typename type_list_unique<type_list<Other...>>::type,
- type_list_cat_t<type_list<Type>, typename type_list_unique<type_list<Other...>>::type>>;
- };
- /*! @brief Removes duplicates types from a type list. */
- template<>
- struct type_list_unique<type_list<>> {
- /*! @brief A type list without duplicate types. */
- using type = type_list<>;
- };
- /**
- * @brief Helper type.
- * @tparam Type A type list.
- */
- template<typename Type>
- using type_list_unique_t = typename type_list_unique<Type>::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::disjunction<std::is_same<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 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 value. */
- static constexpr auto value = Value;
- };
- /**
- * @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 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 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
- * Internal details not to be documented.
- */
- 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
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /*! @copydoc is_iterator */
- template<typename Type>
- struct is_iterator<Type, std::enable_if_t<!std::is_same_v<std::remove_const_t<std::remove_pointer_t<Type>>, void>>>
- : 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::conjunction<std::is_empty<Type>, std::negation<std::is_final<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;
- /**
- * @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, typename = void>
- struct is_equality_comparable: std::false_type {};
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- 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 Type, std::size_t... Index>
- [[nodiscard]] constexpr bool unpack_maybe_equality_comparable(std::index_sequence<Index...>) {
- return (is_equality_comparable<std::tuple_element_t<Index, Type>>::value && ...);
- }
- template<typename>
- [[nodiscard]] constexpr bool maybe_equality_comparable(choice_t<0>) {
- return true;
- }
- template<typename Type>
- [[nodiscard]] constexpr auto maybe_equality_comparable(choice_t<1>) -> decltype(std::declval<typename Type::value_type>(), bool{}) {
- if constexpr(is_iterator_v<Type>) {
- return true;
- } else if constexpr(std::is_same_v<typename Type::value_type, Type>) {
- return maybe_equality_comparable<Type>(choice<0>);
- } else {
- return is_equality_comparable<typename Type::value_type>::value;
- }
- }
- template<typename Type>
- [[nodiscard]] constexpr std::enable_if_t<is_complete_v<std::tuple_size<std::remove_const_t<Type>>>, bool> maybe_equality_comparable(choice_t<2>) {
- if constexpr(has_tuple_size_value<Type>::value) {
- return unpack_maybe_equality_comparable<Type>(std::make_index_sequence<std::tuple_size<Type>::value>{});
- } else {
- return maybe_equality_comparable<Type>(choice<1>);
- }
- }
- } // namespace internal
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /*! @copydoc is_equality_comparable */
- template<typename Type>
- struct is_equality_comparable<Type, std::void_t<decltype(std::declval<Type>() == std::declval<Type>())>>
- : std::bool_constant<internal::maybe_equality_comparable<Type>(choice<2>)> {};
- /**
- * @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 = std::add_const_t<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;
- } // namespace entt
- #endif
- namespace entt {
- /**
- * @brief A SBO friendly, type-safe container for single values of any type.
- * @tparam Len Size of the storage reserved for the small buffer optimization.
- * @tparam Align Optional alignment requirement.
- */
- template<std::size_t Len, std::size_t Align>
- class basic_any {
- enum class operation : std::uint8_t {
- copy,
- move,
- transfer,
- assign,
- destroy,
- compare,
- get
- };
- enum class policy : std::uint8_t {
- owner,
- ref,
- cref
- };
- using storage_type = std::aligned_storage_t<Len + !Len, Align>;
- using vtable_type = const void *(const operation, const basic_any &, const void *);
- template<typename Type>
- static constexpr bool in_situ = Len && alignof(Type) <= alignof(storage_type) && sizeof(Type) <= sizeof(storage_type) && std::is_nothrow_move_constructible_v<Type>;
- template<typename Type>
- static const void *basic_vtable([[maybe_unused]] const operation op, [[maybe_unused]] const basic_any &value, [[maybe_unused]] const void *other) {
- static_assert(!std::is_same_v<Type, void> && std::is_same_v<std::remove_cv_t<std::remove_reference_t<Type>>, Type>, "Invalid type");
- const Type *element = nullptr;
- if constexpr(in_situ<Type>) {
- element = value.owner() ? reinterpret_cast<const Type *>(&value.storage) : static_cast<const Type *>(value.instance);
- } else {
- element = static_cast<const Type *>(value.instance);
- }
- switch(op) {
- case operation::copy:
- if constexpr(std::is_copy_constructible_v<Type>) {
- static_cast<basic_any *>(const_cast<void *>(other))->initialize<Type>(*element);
- }
- break;
- case operation::move:
- if constexpr(in_situ<Type>) {
- if(value.owner()) {
- return new(&static_cast<basic_any *>(const_cast<void *>(other))->storage) Type{std::move(*const_cast<Type *>(element))};
- }
- }
- return (static_cast<basic_any *>(const_cast<void *>(other))->instance = std::exchange(const_cast<basic_any &>(value).instance, nullptr));
- case operation::transfer:
- if constexpr(std::is_move_assignable_v<Type>) {
- *const_cast<Type *>(element) = std::move(*static_cast<Type *>(const_cast<void *>(other)));
- return other;
- }
- [[fallthrough]];
- case operation::assign:
- if constexpr(std::is_copy_assignable_v<Type>) {
- *const_cast<Type *>(element) = *static_cast<const Type *>(other);
- return other;
- }
- break;
- case operation::destroy:
- if constexpr(in_situ<Type>) {
- element->~Type();
- } else if constexpr(std::is_array_v<Type>) {
- delete[] element;
- } else {
- delete element;
- }
- break;
- case operation::compare:
- if constexpr(!std::is_function_v<Type> && !std::is_array_v<Type> && is_equality_comparable_v<Type>) {
- return *static_cast<const Type *>(element) == *static_cast<const Type *>(other) ? other : nullptr;
- } else {
- return (element == other) ? other : nullptr;
- }
- case operation::get:
- return element;
- }
- return nullptr;
- }
- template<typename Type, typename... Args>
- void initialize([[maybe_unused]] Args &&...args) {
- if constexpr(!std::is_void_v<Type>) {
- info = &type_id<std::remove_cv_t<std::remove_reference_t<Type>>>();
- vtable = basic_vtable<std::remove_cv_t<std::remove_reference_t<Type>>>;
- if constexpr(std::is_lvalue_reference_v<Type>) {
- static_assert(sizeof...(Args) == 1u && (std::is_lvalue_reference_v<Args> && ...), "Invalid arguments");
- mode = std::is_const_v<std::remove_reference_t<Type>> ? policy::cref : policy::ref;
- instance = (std::addressof(args), ...);
- } else if constexpr(in_situ<Type>) {
- if constexpr(sizeof...(Args) != 0u && std::is_aggregate_v<Type>) {
- new(&storage) Type{std::forward<Args>(args)...};
- } else {
- new(&storage) Type(std::forward<Args>(args)...);
- }
- } else {
- if constexpr(sizeof...(Args) != 0u && std::is_aggregate_v<Type>) {
- instance = new Type{std::forward<Args>(args)...};
- } else {
- instance = new Type(std::forward<Args>(args)...);
- }
- }
- }
- }
- basic_any(const basic_any &other, const policy pol) ENTT_NOEXCEPT
- : instance{other.data()},
- info{other.info},
- vtable{other.vtable},
- mode{pol} {}
- public:
- /*! @brief Size of the internal storage. */
- static constexpr auto length = Len;
- /*! @brief Alignment requirement. */
- static constexpr auto alignment = Align;
- /*! @brief Default constructor. */
- constexpr basic_any() ENTT_NOEXCEPT
- : instance{},
- info{&type_id<void>()},
- vtable{},
- mode{policy::owner} {}
- /**
- * @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)
- : basic_any{} {
- initialize<Type>(std::forward<Args>(args)...);
- }
- /**
- * @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{} {
- initialize<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{} {
- if(other.vtable) {
- other.vtable(operation::copy, other, this);
- }
- }
- /**
- * @brief Move constructor.
- * @param other The instance to move from.
- */
- basic_any(basic_any &&other) ENTT_NOEXCEPT
- : instance{},
- info{other.info},
- vtable{other.vtable},
- mode{other.mode} {
- if(other.vtable) {
- other.vtable(operation::move, other, this);
- }
- }
- /*! @brief Frees the internal storage, whatever it means. */
- ~basic_any() {
- if(vtable && owner()) {
- vtable(operation::destroy, *this, nullptr);
- }
- }
- /**
- * @brief Copy assignment operator.
- * @param other The instance to copy from.
- * @return This any object.
- */
- basic_any &operator=(const basic_any &other) {
- reset();
- if(other.vtable) {
- other.vtable(operation::copy, other, this);
- }
- return *this;
- }
- /**
- * @brief Move assignment operator.
- * @param other The instance to move from.
- * @return This any object.
- */
- basic_any &operator=(basic_any &&other) ENTT_NOEXCEPT {
- reset();
- if(other.vtable) {
- other.vtable(operation::move, other, this);
- info = other.info;
- vtable = other.vtable;
- 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>
- 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 the object type if any, `type_id<void>()` otherwise.
- * @return The object type if any, `type_id<void>()` otherwise.
- */
- [[nodiscard]] const type_info &type() const ENTT_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 ENTT_NOEXCEPT {
- return vtable ? vtable(operation::get, *this, nullptr) : nullptr;
- }
- /**
- * @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 ENTT_NOEXCEPT {
- return *info == req ? data() : nullptr;
- }
- /**
- * @brief Returns an opaque pointer to the contained instance.
- * @return An opaque pointer the contained instance, if any.
- */
- [[nodiscard]] void *data() ENTT_NOEXCEPT {
- return (!vtable || mode == policy::cref) ? nullptr : const_cast<void *>(vtable(operation::get, *this, nullptr));
- }
- /**
- * @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) ENTT_NOEXCEPT {
- return *info == req ? data() : nullptr;
- }
- /**
- * @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) {
- reset();
- 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 any &other) {
- if(vtable && mode != policy::cref && *info == *other.info) {
- return (vtable(operation::assign, *this, other.data()) != nullptr);
- }
- return false;
- }
- /*! @copydoc assign */
- bool assign(any &&other) {
- if(vtable && mode != policy::cref && *info == *other.info) {
- if(auto *val = other.data(); val) {
- return (vtable(operation::transfer, *this, val) != nullptr);
- } else {
- return (vtable(operation::assign, *this, std::as_const(other).data()) != nullptr);
- }
- }
- return false;
- }
- /*! @brief Destroys contained object */
- void reset() {
- if(vtable && owner()) {
- vtable(operation::destroy, *this, nullptr);
- }
- info = &type_id<void>();
- vtable = nullptr;
- mode = policy::owner;
- }
- /**
- * @brief Returns false if a wrapper is empty, true otherwise.
- * @return False if the wrapper is empty, true otherwise.
- */
- [[nodiscard]] explicit operator bool() const ENTT_NOEXCEPT {
- return vtable != nullptr;
- }
- /**
- * @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.
- */
- bool operator==(const basic_any &other) const ENTT_NOEXCEPT {
- if(vtable && *info == *other.info) {
- return (vtable(operation::compare, *this, other.data()) != nullptr);
- }
- return (!vtable && !other.vtable);
- }
- /**
- * @brief Aliasing constructor.
- * @return A wrapper that shares a reference to an unmanaged object.
- */
- [[nodiscard]] basic_any as_ref() ENTT_NOEXCEPT {
- return basic_any{*this, (mode == policy::cref ? policy::cref : policy::ref)};
- }
- /*! @copydoc as_ref */
- [[nodiscard]] basic_any as_ref() const ENTT_NOEXCEPT {
- return basic_any{*this, policy::cref};
- }
- /**
- * @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 ENTT_NOEXCEPT {
- return (mode == policy::owner);
- }
- private:
- union {
- const void *instance;
- storage_type storage;
- };
- const type_info *info;
- vtable_type *vtable;
- policy mode;
- };
- /**
- * @brief Checks if two wrappers differ in their content.
- * @tparam Len Size of the storage reserved for the small buffer optimization.
- * @tparam Align Alignment requirement.
- * @param lhs A wrapper, either empty or not.
- * @param rhs A wrapper, either empty or not.
- * @return True if the two wrappers differ in their content, false otherwise.
- */
- template<std::size_t Len, std::size_t Align>
- [[nodiscard]] inline bool operator!=(const basic_any<Len, Align> &lhs, const basic_any<Len, Align> &rhs) ENTT_NOEXCEPT {
- return !(lhs == rhs);
- }
- /**
- * @brief Performs type-safe access to the contained object.
- * @tparam Type Type to which conversion is required.
- * @tparam Len Size of the storage 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>
- Type any_cast(const basic_any<Len, Align> &data) ENTT_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>
- Type any_cast(basic_any<Len, Align> &data) ENTT_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>
- Type any_cast(basic_any<Len, Align> &&data) ENTT_NOEXCEPT {
- if constexpr(std::is_copy_constructible_v<std::remove_cv_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));
- } else {
- 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>
- const Type *any_cast(const basic_any<Len, Align> *data) ENTT_NOEXCEPT {
- const auto &info = type_id<std::remove_cv_t<std::remove_reference_t<Type>>>();
- return static_cast<const Type *>(data->data(info));
- }
- /*! @copydoc any_cast */
- template<typename Type, std::size_t Len, std::size_t Align>
- Type *any_cast(basic_any<Len, Align> *data) ENTT_NOEXCEPT {
- const auto &info = type_id<std::remove_cv_t<std::remove_reference_t<Type>>>();
- // last attempt to make wrappers for const references return their values
- return static_cast<Type *>(static_cast<constness_as_t<basic_any<Len, Align>, Type> *>(data)->data(info));
- }
- /**
- * @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 storage 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>
- 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 storage 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>
- basic_any<Len, Align> forward_as_any(Type &&value) {
- return basic_any<Len, Align>{std::in_place_type<std::conditional_t<std::is_rvalue_reference_v<Type>, std::decay_t<Type>, Type>>, std::forward<Type>(value)};
- }
- } // namespace entt
- #endif
- // #include "core/attribute.h"
- #ifndef ENTT_CORE_ATTRIBUTE_H
- #define ENTT_CORE_ATTRIBUTE_H
- #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
- #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 "../config/config.h"
- // #include "type_traits.hpp"
- namespace entt {
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- namespace internal {
- template<typename Type, std::size_t, typename = void>
- struct compressed_pair_element {
- using reference = Type &;
- using const_reference = const Type &;
- template<bool Dummy = true, typename = std::enable_if_t<Dummy && std::is_default_constructible_v<Type>>>
- compressed_pair_element()
- : value{} {}
- template<typename Args, typename = std::enable_if_t<!std::is_same_v<std::remove_cv_t<std::remove_reference_t<Args>>, compressed_pair_element>>>
- compressed_pair_element(Args &&args)
- : value{std::forward<Args>(args)} {}
- template<typename... Args, std::size_t... Index>
- compressed_pair_element(std::tuple<Args...> args, std::index_sequence<Index...>)
- : value{std::forward<Args>(std::get<Index>(args))...} {}
- [[nodiscard]] reference get() ENTT_NOEXCEPT {
- return value;
- }
- [[nodiscard]] const_reference get() const ENTT_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<bool Dummy = true, typename = std::enable_if_t<Dummy && std::is_default_constructible_v<base_type>>>
- compressed_pair_element()
- : base_type{} {}
- template<typename Args, typename = std::enable_if_t<!std::is_same_v<std::remove_cv_t<std::remove_reference_t<Args>>, compressed_pair_element>>>
- compressed_pair_element(Args &&args)
- : base_type{std::forward<Args>(args)} {}
- template<typename... Args, std::size_t... Index>
- compressed_pair_element(std::tuple<Args...> args, std::index_sequence<Index...>)
- : base_type{std::forward<Args>(std::get<Index>(args))...} {}
- [[nodiscard]] reference get() ENTT_NOEXCEPT {
- return *this;
- }
- [[nodiscard]] const_reference get() const ENTT_NOEXCEPT {
- return *this;
- }
- };
- } // namespace internal
- /**
- * Internal details not to be documented.
- * @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()
- : 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) = 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)
- : 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)
- : first_base{std::move(args), std::index_sequence_for<Args...>{}},
- second_base{std::move(other), std::index_sequence_for<Other...>{}} {}
- /**
- * @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) = default;
- /**
- * @brief Returns the first element that a pair stores.
- * @return The first element that a pair stores.
- */
- [[nodiscard]] first_type &first() ENTT_NOEXCEPT {
- return static_cast<first_base &>(*this).get();
- }
- /*! @copydoc first */
- [[nodiscard]] const first_type &first() const ENTT_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]] second_type &second() ENTT_NOEXCEPT {
- return static_cast<second_base &>(*this).get();
- }
- /*! @copydoc second */
- [[nodiscard]] const second_type &second() const ENTT_NOEXCEPT {
- return static_cast<const second_base &>(*this).get();
- }
- /**
- * @brief Swaps two compressed pair objects.
- * @param other The compressed pair to swap with.
- */
- void swap(compressed_pair &other) {
- 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>
- decltype(auto) get() ENTT_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>
- decltype(auto) get() const ENTT_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>
- inline void swap(compressed_pair<First, Second> &lhs, compressed_pair<First, Second> &rhs) {
- lhs.swap(rhs);
- }
- } // namespace entt
- // disable structured binding support for clang 6, it messes when specializing tuple_size
- #if !defined __clang_major__ || __clang_major__ > 6
- 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
- #endif
- // #include "core/enum.hpp"
- #ifndef ENTT_CORE_ENUM_HPP
- #define ENTT_CORE_ENUM_HPP
- #include <type_traits>
- // #include "../config/config.h"
- 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) ENTT_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) ENTT_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) ENTT_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) ENTT_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) ENTT_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) ENTT_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) ENTT_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) ENTT_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 {
- inline static ENTT_MAYBE_ATOMIC(id_type) identifier{};
- public:
- /*! @brief Unsigned integer type. */
- using family_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 family_type type = 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 "../config/config.h"
- // #include "fwd.hpp"
- namespace entt {
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- namespace internal {
- template<typename>
- struct fnv1a_traits;
- template<>
- struct fnv1a_traits<std::uint32_t> {
- using type = std::uint32_t;
- static constexpr std::uint32_t offset = 2166136261;
- static constexpr std::uint32_t prime = 16777619;
- };
- template<>
- struct fnv1a_traits<std::uint64_t> {
- using type = std::uint64_t;
- static constexpr std::uint64_t offset = 14695981039346656037ull;
- static constexpr std::uint64_t 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;
- size_type length;
- hash_type hash;
- };
- } // namespace internal
- /**
- * Internal details not to be documented.
- * @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 hs_traits = internal::fnv1a_traits<id_type>;
- struct const_wrapper {
- // non-explicit constructor on purpose
- constexpr const_wrapper(const Char *str) ENTT_NOEXCEPT: repr{str} {}
- const Char *repr;
- };
- // Fowler–Noll–Vo hash function v. 1a - the good
- [[nodiscard]] static constexpr auto helper(const Char *str) ENTT_NOEXCEPT {
- base_type base{str, 0u, hs_traits::offset};
- for(; str[base.length]; ++base.length) {
- base.hash = (base.hash ^ static_cast<hs_traits::type>(str[base.length])) * hs_traits::prime;
- }
- return base;
- }
- // Fowler–Noll–Vo hash function v. 1a - the good
- [[nodiscard]] static constexpr auto helper(const Char *str, const std::size_t len) ENTT_NOEXCEPT {
- base_type base{str, len, hs_traits::offset};
- for(size_type pos{}; pos < len; ++pos) {
- base.hash = (base.hash ^ static_cast<hs_traits::type>(str[pos])) * hs_traits::prime;
- }
- return base;
- }
- 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) ENTT_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>
- [[nodiscard]] static constexpr hash_type value(const value_type (&str)[N]) ENTT_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) ENTT_NOEXCEPT {
- return basic_hashed_string{wrapper};
- }
- /*! @brief Constructs an empty hashed string. */
- constexpr basic_hashed_string() ENTT_NOEXCEPT
- : base_type{} {}
- /**
- * @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) ENTT_NOEXCEPT
- : base_type{helper(str, len)} {}
- /**
- * @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>
- constexpr basic_hashed_string(const value_type (&str)[N]) ENTT_NOEXCEPT
- : base_type{helper(str)} {}
- /**
- * @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) ENTT_NOEXCEPT
- : base_type{helper(wrapper.repr)} {}
- /**
- * @brief Returns the size a hashed string.
- * @return The size of the hashed string.
- */
- [[nodiscard]] constexpr size_type size() const ENTT_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 ENTT_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 ENTT_NOEXCEPT {
- return base_type::hash;
- }
- /*! @copydoc data */
- [[nodiscard]] constexpr operator const value_type *() const ENTT_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 ENTT_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, const 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>
- 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) ENTT_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) ENTT_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) ENTT_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) ENTT_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) ENTT_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) ENTT_NOEXCEPT {
- return !(lhs < rhs);
- }
- /*! @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>;
- inline namespace literals {
- /**
- * @brief User defined literal for hashed strings.
- * @param str The literal without its suffix.
- * @return A properly initialized hashed string.
- */
- [[nodiscard]] constexpr hashed_string operator"" _hs(const char *str, std::size_t) ENTT_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]] constexpr hashed_wstring operator"" _hws(const wchar_t *str, std::size_t) ENTT_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 "../config/config.h"
- // #include "fwd.hpp"
- // #include "type_traits.hpp"
- namespace entt {
- /**
- * @brief Types identifiers.
- *
- * Variable template used to generate identifiers at compile-time for the given
- * types. Use the `get` member function to know what's the identifier associated
- * to the specific type.
- *
- * @note
- * Identifiers are constant expression and can be used in any context where such
- * an expression is required. As an example:
- * @code{.cpp}
- * using id = entt::identifier<a_type, another_type>;
- *
- * switch(a_type_identifier) {
- * case id::type<a_type>:
- * // ...
- * break;
- * case id::type<another_type>:
- * // ...
- * break;
- * default:
- * // ...
- * }
- * @endcode
- *
- * @tparam Types List of types for which to generate identifiers.
- */
- template<typename... Types>
- class identifier {
- template<typename Type, std::size_t... Index>
- [[nodiscard]] static constexpr id_type get(std::index_sequence<Index...>) ENTT_NOEXCEPT {
- static_assert((std::is_same_v<Type, Types> || ...), "Invalid type");
- return (0 + ... + (std::is_same_v<Type, type_list_element_t<Index, type_list<std::decay_t<Types>...>>> ? id_type{Index} : id_type{}));
- }
- public:
- /*! @brief Unsigned integer type. */
- using identifier_type = id_type;
- /*! @brief Statically generated unique identifier for the given type. */
- template<typename Type>
- static constexpr identifier_type type = get<std::decay_t<Type>>(std::index_sequence_for<Types...>{});
- };
- } // namespace entt
- #endif
- // #include "core/iterator.hpp"
- #ifndef ENTT_CORE_ITERATOR_HPP
- #define ENTT_CORE_ITERATOR_HPP
- #include <iterator>
- #include <memory>
- #include <utility>
- // #include "../config/config.h"
- 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 Pointer type. */
- using pointer = Type *;
- /*! @brief Default copy constructor, deleted on purpose. */
- input_iterator_pointer(const input_iterator_pointer &) = delete;
- /*! @brief Default move constructor. */
- input_iterator_pointer(input_iterator_pointer &&) = default;
- /**
- * @brief Constructs a proxy object by move.
- * @param val Value to use to initialize the proxy object.
- */
- input_iterator_pointer(Type &&val)
- : value{std::move(val)} {}
- /**
- * @brief Default copy assignment operator, deleted on purpose.
- * @return This proxy object.
- */
- input_iterator_pointer &operator=(const input_iterator_pointer &) = delete;
- /**
- * @brief Default move assignment operator.
- * @return This proxy object.
- */
- input_iterator_pointer &operator=(input_iterator_pointer &&) = default;
- /**
- * @brief Access operator for accessing wrapped values.
- * @return A pointer to the wrapped value.
- */
- [[nodiscard]] pointer operator->() ENTT_NOEXCEPT {
- return std::addressof(value);
- }
- private:
- Type value;
- };
- /**
- * @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. */
- iterable_adaptor() = default;
- /**
- * @brief Creates an iterable object from a pair of iterators.
- * @param from Begin iterator.
- * @param to End iterator.
- */
- iterable_adaptor(iterator from, sentinel to)
- : first{from},
- last{to} {}
- /**
- * @brief Returns an iterator to the beginning.
- * @return An iterator to the first element of the range.
- */
- [[nodiscard]] iterator begin() const ENTT_NOEXCEPT {
- return first;
- }
- /**
- * @brief Returns an iterator to the end.
- * @return An iterator to the element following the last element of the
- * range.
- */
- [[nodiscard]] sentinel end() const ENTT_NOEXCEPT {
- return last;
- }
- /*! @copydoc begin */
- [[nodiscard]] iterator cbegin() const ENTT_NOEXCEPT {
- return begin();
- }
- /*! @copydoc end */
- [[nodiscard]] sentinel cend() const ENTT_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 <limits>
- #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) ENTT_NOEXCEPT {
- if constexpr(std::is_pointer_v<std::remove_cv_t<std::remove_reference_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) ENTT_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) ENTT_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) ENTT_NOEXCEPT {
- ENTT_ASSERT(std::allocator_traits<Allocator>::propagate_on_container_swap::value || lhs == rhs, "Cannot swap the containers");
- if constexpr(std::allocator_traits<Allocator>::propagate_on_container_swap::value) {
- using std::swap;
- swap(lhs, rhs);
- }
- }
- /**
- * @brief Checks whether a value is a power of two or not.
- * @param value A value that may or may not be a power of two.
- * @return True if the value is a power of two, false otherwise.
- */
- [[nodiscard]] inline constexpr bool is_power_of_two(const std::size_t value) ENTT_NOEXCEPT {
- return value && ((value & (value - 1)) == 0);
- }
- /**
- * @brief Computes the smallest power of two greater than or equal to a value.
- * @param value The value to use.
- * @return The smallest power of two greater than or equal to the given value.
- */
- [[nodiscard]] inline constexpr std::size_t next_power_of_two(const std::size_t value) ENTT_NOEXCEPT {
- ENTT_ASSERT(value < (std::size_t{1u} << (std::numeric_limits<std::size_t>::digits - 1)), "Numeric limits exceeded");
- std::size_t curr = value - (value != 0u);
- for(int next = 1; next < std::numeric_limits<std::size_t>::digits; next = next * 2) {
- curr |= curr >> next;
- }
- return ++curr;
- }
- /**
- * @brief Fast module utility function (powers of two only).
- * @param value A value for which to calculate the modulus.
- * @param mod _Modulus_, it must be a power of two.
- * @return The common remainder.
- */
- [[nodiscard]] inline constexpr std::size_t fast_mod(const std::size_t value, const std::size_t mod) ENTT_NOEXCEPT {
- ENTT_ASSERT(is_power_of_two(mod), "Value must be a power of two");
- return value & (mod - 1u);
- }
- /**
- * @brief Deleter for allocator-aware unique pointers (waiting for C++20).
- * @tparam Args Types of arguments to use to construct the object.
- */
- 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.
- */
- allocation_deleter(const allocator_type &alloc)
- : Allocator{alloc} {}
- /**
- * @brief Destroys the pointed object and deallocates its memory.
- * @param ptr A valid pointer to an object of the given type.
- */
- void operator()(pointer ptr) {
- using alloc_traits = typename 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>
- 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
- * Internal details not to be documented.
- */
- 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) ENTT_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) ENTT_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) ENTT_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) ENTT_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) ENTT_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) ENTT_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
- /**
- * Internal details not to be documented.
- * @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) ENTT_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([&](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.
- */
- template<typename Type>
- void operator=(Type val) const ENTT_NOEXCEPT {
- value<Type> = val;
- }
- /**
- * @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 ENTT_NOEXCEPT {
- return value<Type>;
- }
- private:
- template<typename Type>
- inline static ENTT_MAYBE_ATOMIC(Type) value{};
- };
- /**
- * @brief Helper variable template.
- * @tparam Value Value used to differentiate between different variables.
- */
- template<id_type Value>
- inline monostate<Value> monostate_v = {};
- } // namespace entt
- #endif
- // #include "core/tuple.hpp"
- #ifndef ENTT_CORE_TUPLE_HPP
- #define ENTT_CORE_TUPLE_HPP
- #include <tuple>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- namespace entt {
- /**
- * @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) ENTT_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);
- }
- }
- } // 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 "../core/attribute.h"
- // #include "fwd.hpp"
- // #include "hashed_string.hpp"
- namespace entt {
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- namespace internal {
- struct ENTT_API type_index final {
- [[nodiscard]] static id_type next() ENTT_NOEXCEPT {
- static ENTT_MAYBE_ATOMIC(id_type) value{};
- return value++;
- }
- };
- template<typename Type>
- [[nodiscard]] constexpr auto stripped_type_name() ENTT_NOEXCEPT {
- #if defined ENTT_PRETTY_FUNCTION
- std::string_view pretty_function{ENTT_PRETTY_FUNCTION};
- auto first = pretty_function.find_first_not_of(' ', pretty_function.find_first_of(ENTT_PRETTY_FUNCTION_PREFIX) + 1);
- auto value = pretty_function.substr(first, pretty_function.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]] static constexpr std::string_view type_name(int) ENTT_NOEXCEPT {
- constexpr auto value = stripped_type_name<Type>();
- return value;
- }
- template<typename Type>
- [[nodiscard]] static std::string_view type_name(char) ENTT_NOEXCEPT {
- static const auto value = stripped_type_name<Type>();
- return value;
- }
- template<typename Type, auto = stripped_type_name<Type>().find_first_of('.')>
- [[nodiscard]] static constexpr id_type type_hash(int) ENTT_NOEXCEPT {
- constexpr auto stripped = stripped_type_name<Type>();
- constexpr auto value = hashed_string::value(stripped.data(), stripped.size());
- return value;
- }
- template<typename Type>
- [[nodiscard]] static id_type type_hash(char) ENTT_NOEXCEPT {
- static const auto value = [](const auto stripped) {
- return hashed_string::value(stripped.data(), stripped.size());
- }(stripped_type_name<Type>());
- return value;
- }
- } // namespace internal
- /**
- * Internal details not to be documented.
- * @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() ENTT_NOEXCEPT {
- static const id_type value = internal::type_index::next();
- return value;
- }
- /*! @copydoc value */
- [[nodiscard]] constexpr operator id_type() const ENTT_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() ENTT_NOEXCEPT {
- return internal::type_hash<Type>(0);
- #else
- [[nodiscard]] static constexpr id_type value() ENTT_NOEXCEPT {
- return type_index<Type>::value();
- #endif
- }
- /*! @copydoc value */
- [[nodiscard]] constexpr operator id_type() const ENTT_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() ENTT_NOEXCEPT {
- return internal::type_name<Type>(0);
- }
- /*! @copydoc value */
- [[nodiscard]] constexpr operator std::string_view() const ENTT_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>
- constexpr type_info(std::in_place_type_t<Type>) ENTT_NOEXCEPT
- : seq{type_index<std::remove_cv_t<std::remove_reference_t<Type>>>::value()},
- identifier{type_hash<std::remove_cv_t<std::remove_reference_t<Type>>>::value()},
- alias{type_name<std::remove_cv_t<std::remove_reference_t<Type>>>::value()} {}
- /**
- * @brief Type index.
- * @return Type index.
- */
- [[nodiscard]] constexpr id_type index() const ENTT_NOEXCEPT {
- return seq;
- }
- /**
- * @brief Type hash.
- * @return Type hash.
- */
- [[nodiscard]] constexpr id_type hash() const ENTT_NOEXCEPT {
- return identifier;
- }
- /**
- * @brief Type name.
- * @return Type name.
- */
- [[nodiscard]] constexpr std::string_view name() const ENTT_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]] inline constexpr bool operator==(const type_info &lhs, const type_info &rhs) ENTT_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]] inline constexpr bool operator!=(const type_info &lhs, const type_info &rhs) ENTT_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) ENTT_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) ENTT_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) ENTT_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) ENTT_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() ENTT_NOEXCEPT {
- if constexpr(std::is_same_v<Type, std::remove_cv_t<std::remove_reference_t<Type>>>) {
- static type_info instance{std::in_place_type<Type>};
- return instance;
- } else {
- return type_id<std::remove_cv_t<std::remove_reference_t<Type>>>();
- }
- }
- /*! @copydoc type_id */
- template<typename Type>
- [[nodiscard]] const type_info &type_id(Type &&) ENTT_NOEXCEPT {
- return type_id<std::remove_cv_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 <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.
- * @tparam The size of the type if `sizeof` accepts it, 0 otherwise.
- */
- 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))>>
- : 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 Type First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<std::size_t Index, typename Type, typename... Other>
- struct type_list_element<Index, type_list<Type, Other...>>
- : type_list_element<Index - 1u, type_list<Other...>> {};
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam Type First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<typename Type, typename... Other>
- struct type_list_element<0u, type_list<Type, Other...>> {
- /*! @brief Searched type. */
- using type = Type;
- };
- /**
- * @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 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;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename>
- struct type_list_unique;
- /**
- * @brief Removes duplicates types from a type list.
- * @tparam Type One of the types provided by the given type list.
- * @tparam Other The other types provided by the given type list.
- */
- template<typename Type, typename... Other>
- struct type_list_unique<type_list<Type, Other...>> {
- /*! @brief A type list without duplicate types. */
- using type = std::conditional_t<
- (std::is_same_v<Type, Other> || ...),
- typename type_list_unique<type_list<Other...>>::type,
- type_list_cat_t<type_list<Type>, typename type_list_unique<type_list<Other...>>::type>>;
- };
- /*! @brief Removes duplicates types from a type list. */
- template<>
- struct type_list_unique<type_list<>> {
- /*! @brief A type list without duplicate types. */
- using type = type_list<>;
- };
- /**
- * @brief Helper type.
- * @tparam Type A type list.
- */
- template<typename Type>
- using type_list_unique_t = typename type_list_unique<Type>::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::disjunction<std::is_same<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 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 value. */
- static constexpr auto value = Value;
- };
- /**
- * @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 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 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
- * Internal details not to be documented.
- */
- 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
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /*! @copydoc is_iterator */
- template<typename Type>
- struct is_iterator<Type, std::enable_if_t<!std::is_same_v<std::remove_const_t<std::remove_pointer_t<Type>>, void>>>
- : 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::conjunction<std::is_empty<Type>, std::negation<std::is_final<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;
- /**
- * @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, typename = void>
- struct is_equality_comparable: std::false_type {};
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- 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 Type, std::size_t... Index>
- [[nodiscard]] constexpr bool unpack_maybe_equality_comparable(std::index_sequence<Index...>) {
- return (is_equality_comparable<std::tuple_element_t<Index, Type>>::value && ...);
- }
- template<typename>
- [[nodiscard]] constexpr bool maybe_equality_comparable(choice_t<0>) {
- return true;
- }
- template<typename Type>
- [[nodiscard]] constexpr auto maybe_equality_comparable(choice_t<1>) -> decltype(std::declval<typename Type::value_type>(), bool{}) {
- if constexpr(is_iterator_v<Type>) {
- return true;
- } else if constexpr(std::is_same_v<typename Type::value_type, Type>) {
- return maybe_equality_comparable<Type>(choice<0>);
- } else {
- return is_equality_comparable<typename Type::value_type>::value;
- }
- }
- template<typename Type>
- [[nodiscard]] constexpr std::enable_if_t<is_complete_v<std::tuple_size<std::remove_const_t<Type>>>, bool> maybe_equality_comparable(choice_t<2>) {
- if constexpr(has_tuple_size_value<Type>::value) {
- return unpack_maybe_equality_comparable<Type>(std::make_index_sequence<std::tuple_size<Type>::value>{});
- } else {
- return maybe_equality_comparable<Type>(choice<1>);
- }
- }
- } // namespace internal
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /*! @copydoc is_equality_comparable */
- template<typename Type>
- struct is_equality_comparable<Type, std::void_t<decltype(std::declval<Type>() == std::declval<Type>())>>
- : std::bool_constant<internal::maybe_equality_comparable<Type>(choice<2>)> {};
- /**
- * @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 = std::add_const_t<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;
- } // namespace entt
- #endif
- // #include "core/utility.hpp"
- #ifndef ENTT_CORE_UTILITY_HPP
- #define ENTT_CORE_UTILITY_HPP
- #include <utility>
- // #include "../config/config.h"
- 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<class Type>
- [[nodiscard]] constexpr Type &&operator()(Type &&value) const ENTT_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) ENTT_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) ENTT_NOEXCEPT {
- return func;
- }
- /**
- * @brief Helper type for visitors.
- * @tparam Func Types of function objects.
- */
- template<class... Func>
- struct overloaded: Func... {
- using Func::operator()...;
- };
- /**
- * @brief Deduction guide.
- * @tparam Func Types of function objects.
- */
- template<class... Func>
- overloaded(Func...) -> overloaded<Func...>;
- /**
- * @brief Basic implementation of a y-combinator.
- * @tparam Func Type of a potentially recursive function.
- */
- template<class Func>
- struct y_combinator {
- /**
- * @brief Constructs a y-combinator from a given function.
- * @param recursive A potentially recursive function.
- */
- y_combinator(Func recursive)
- : 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<class... Args>
- decltype(auto) operator()(Args &&...args) const {
- return func(*this, std::forward<Args>(args)...);
- }
- /*! @copydoc operator()() */
- template<class... Args>
- decltype(auto) operator()(Args &&...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
- #define ENTT_STR(arg) #arg
- #define ENTT_XSTR(arg) ENTT_STR(arg)
- #endif
- #define ENTT_VERSION_MAJOR 3
- #define ENTT_VERSION_MINOR 10
- #define ENTT_VERSION_PATCH 3
- #define ENTT_VERSION \
- ENTT_XSTR(ENTT_VERSION_MAJOR) \
- "." ENTT_XSTR(ENTT_VERSION_MINOR) "." ENTT_XSTR(ENTT_VERSION_PATCH)
- #endif
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #ifndef ENTT_NOEXCEPT
- # define ENTT_NOEXCEPT noexcept
- # define ENTT_NOEXCEPT_IF(expr) noexcept(expr)
- # else
- # define ENTT_NOEXCEPT_IF(...)
- #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
- #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(...) (void(0))
- #elif !defined ENTT_ASSERT
- # include <cassert>
- # define ENTT_ASSERT(condition, ...) assert(condition)
- #endif
- #ifdef ENTT_NO_ETO
- # define ENTT_IGNORE_IF_EMPTY false
- #else
- # define ENTT_IGNORE_IF_EMPTY true
- #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
- #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
- #endif
- namespace entt {
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- namespace internal {
- template<typename, typename = void>
- struct in_place_delete: 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, (ENTT_IGNORE_IF_EMPTY && std::is_empty_v<Type>) ? 0u : ENTT_PACKED_PAGE> {};
- template<typename Type>
- struct page_size<Type, std::enable_if_t<std::is_convertible_v<decltype(Type::page_size), std::size_t>>>
- : std::integral_constant<std::size_t, Type::page_size> {};
- } // namespace internal
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /**
- * @brief Common way to access various properties of components.
- * @tparam Type Type of component.
- */
- template<typename Type, typename = void>
- struct component_traits {
- static_assert(std::is_same_v<std::decay_t<Type>, Type>, "Unsupported type");
- /*! @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;
- };
- /**
- * @brief Helper variable template.
- * @tparam Type Type of component.
- */
- template<class Type>
- inline constexpr bool ignore_as_empty_v = (component_traits<Type>::page_size == 0u);
- } // 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 "fwd.hpp"
- #ifndef ENTT_ENTITY_FWD_HPP
- #define ENTT_ENTITY_FWD_HPP
- #include <memory>
- // #include "../core/fwd.hpp"
- #ifndef ENTT_CORE_FWD_HPP
- #define ENTT_CORE_FWD_HPP
- #include <cstdint>
- #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
- #define ENTT_STR(arg) #arg
- #define ENTT_XSTR(arg) ENTT_STR(arg)
- #endif
- #define ENTT_VERSION_MAJOR 3
- #define ENTT_VERSION_MINOR 10
- #define ENTT_VERSION_PATCH 3
- #define ENTT_VERSION \
- ENTT_XSTR(ENTT_VERSION_MAJOR) \
- "." ENTT_XSTR(ENTT_VERSION_MINOR) "." ENTT_XSTR(ENTT_VERSION_PATCH)
- #endif
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #ifndef ENTT_NOEXCEPT
- # define ENTT_NOEXCEPT noexcept
- # define ENTT_NOEXCEPT_IF(expr) noexcept(expr)
- # else
- # define ENTT_NOEXCEPT_IF(...)
- #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
- #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(...) (void(0))
- #elif !defined ENTT_ASSERT
- # include <cassert>
- # define ENTT_ASSERT(condition, ...) assert(condition)
- #endif
- #ifdef ENTT_NO_ETO
- # define ENTT_IGNORE_IF_EMPTY false
- #else
- # define ENTT_IGNORE_IF_EMPTY true
- #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
- #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
- #endif
- namespace entt {
- template<std::size_t Len = sizeof(double[2]), std::size_t = alignof(typename std::aligned_storage_t<Len + !Len>)>
- 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<>;
- } // namespace entt
- #endif
- // #include "utility.hpp"
- #ifndef ENTT_ENTITY_UTILITY_HPP
- #define ENTT_ENTITY_UTILITY_HPP
- // #include "../core/type_traits.hpp"
- #ifndef ENTT_CORE_TYPE_TRAITS_HPP
- #define ENTT_CORE_TYPE_TRAITS_HPP
- #include <cstddef>
- #include <iterator>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- // #include "fwd.hpp"
- #ifndef ENTT_CORE_FWD_HPP
- #define ENTT_CORE_FWD_HPP
- #include <cstdint>
- #include <type_traits>
- // #include "../config/config.h"
- namespace entt {
- template<std::size_t Len = sizeof(double[2]), std::size_t = alignof(typename std::aligned_storage_t<Len + !Len>)>
- 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<>;
- } // 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.
- * @tparam The size of the type if `sizeof` accepts it, 0 otherwise.
- */
- 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))>>
- : 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 Type First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<std::size_t Index, typename Type, typename... Other>
- struct type_list_element<Index, type_list<Type, Other...>>
- : type_list_element<Index - 1u, type_list<Other...>> {};
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam Type First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<typename Type, typename... Other>
- struct type_list_element<0u, type_list<Type, Other...>> {
- /*! @brief Searched type. */
- using type = Type;
- };
- /**
- * @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 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;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename>
- struct type_list_unique;
- /**
- * @brief Removes duplicates types from a type list.
- * @tparam Type One of the types provided by the given type list.
- * @tparam Other The other types provided by the given type list.
- */
- template<typename Type, typename... Other>
- struct type_list_unique<type_list<Type, Other...>> {
- /*! @brief A type list without duplicate types. */
- using type = std::conditional_t<
- (std::is_same_v<Type, Other> || ...),
- typename type_list_unique<type_list<Other...>>::type,
- type_list_cat_t<type_list<Type>, typename type_list_unique<type_list<Other...>>::type>>;
- };
- /*! @brief Removes duplicates types from a type list. */
- template<>
- struct type_list_unique<type_list<>> {
- /*! @brief A type list without duplicate types. */
- using type = type_list<>;
- };
- /**
- * @brief Helper type.
- * @tparam Type A type list.
- */
- template<typename Type>
- using type_list_unique_t = typename type_list_unique<Type>::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::disjunction<std::is_same<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 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 value. */
- static constexpr auto value = Value;
- };
- /**
- * @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 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 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
- * Internal details not to be documented.
- */
- 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
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /*! @copydoc is_iterator */
- template<typename Type>
- struct is_iterator<Type, std::enable_if_t<!std::is_same_v<std::remove_const_t<std::remove_pointer_t<Type>>, void>>>
- : 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::conjunction<std::is_empty<Type>, std::negation<std::is_final<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;
- /**
- * @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, typename = void>
- struct is_equality_comparable: std::false_type {};
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- 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 Type, std::size_t... Index>
- [[nodiscard]] constexpr bool unpack_maybe_equality_comparable(std::index_sequence<Index...>) {
- return (is_equality_comparable<std::tuple_element_t<Index, Type>>::value && ...);
- }
- template<typename>
- [[nodiscard]] constexpr bool maybe_equality_comparable(choice_t<0>) {
- return true;
- }
- template<typename Type>
- [[nodiscard]] constexpr auto maybe_equality_comparable(choice_t<1>) -> decltype(std::declval<typename Type::value_type>(), bool{}) {
- if constexpr(is_iterator_v<Type>) {
- return true;
- } else if constexpr(std::is_same_v<typename Type::value_type, Type>) {
- return maybe_equality_comparable<Type>(choice<0>);
- } else {
- return is_equality_comparable<typename Type::value_type>::value;
- }
- }
- template<typename Type>
- [[nodiscard]] constexpr std::enable_if_t<is_complete_v<std::tuple_size<std::remove_const_t<Type>>>, bool> maybe_equality_comparable(choice_t<2>) {
- if constexpr(has_tuple_size_value<Type>::value) {
- return unpack_maybe_equality_comparable<Type>(std::make_index_sequence<std::tuple_size<Type>::value>{});
- } else {
- return maybe_equality_comparable<Type>(choice<1>);
- }
- }
- } // namespace internal
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /*! @copydoc is_equality_comparable */
- template<typename Type>
- struct is_equality_comparable<Type, std::void_t<decltype(std::declval<Type>() == std::declval<Type>())>>
- : std::bool_constant<internal::maybe_equality_comparable<Type>(choice<2>)> {};
- /**
- * @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 = std::add_const_t<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;
- } // namespace entt
- #endif
- namespace entt {
- /**
- * @brief Alias for exclusion lists.
- * @tparam Type List of types.
- */
- template<typename... Type>
- struct exclude_t: type_list<Type...> {};
- /**
- * @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 components.
- * @tparam Type List of types.
- */
- template<typename... Type>
- struct get_t: type_list<Type...> {};
- /**
- * @brief Variable template for lists of observed components.
- * @tparam Type List of types.
- */
- template<typename... Type>
- inline constexpr get_t<Type...> get{};
- /**
- * @brief Alias for lists of owned components.
- * @tparam Type List of types.
- */
- template<typename... Type>
- struct owned_t: type_list<Type...> {};
- /**
- * @brief Variable template for lists of owned components.
- * @tparam Type List of types.
- */
- template<typename... Type>
- inline constexpr owned_t<Type...> owned{};
- } // namespace entt
- #endif
- namespace entt {
- template<typename Entity, typename = std::allocator<Entity>>
- class basic_sparse_set;
- template<typename, typename Type, typename = std::allocator<Type>, typename = void>
- class basic_storage;
- template<typename>
- class basic_registry;
- template<typename, typename, typename, typename = void>
- class basic_view;
- template<typename>
- struct basic_runtime_view;
- template<typename, typename, typename, typename>
- class basic_group;
- template<typename>
- class basic_observer;
- template<typename>
- class basic_organizer;
- template<typename, typename...>
- struct basic_handle;
- template<typename>
- class basic_snapshot;
- template<typename>
- class basic_snapshot_loader;
- template<typename>
- class basic_continuous_loader;
- /*! @brief Default entity identifier. */
- enum class entity : id_type {};
- /*! @brief Alias declaration for the most common use case. */
- using sparse_set = basic_sparse_set<entity>;
- /**
- * @brief Alias declaration for the most common use case.
- * @tparam Args Other template parameters.
- */
- template<typename... Args>
- using storage = basic_storage<entity, Args...>;
- /*! @brief Alias declaration for the most common use case. */
- using registry = basic_registry<entity>;
- /*! @brief Alias declaration for the most common use case. */
- using observer = basic_observer<entity>;
- /*! @brief Alias declaration for the most common use case. */
- using organizer = basic_organizer<entity>;
- /*! @brief Alias declaration for the most common use case. */
- using handle = basic_handle<entity>;
- /*! @brief Alias declaration for the most common use case. */
- using const_handle = basic_handle<const entity>;
- /**
- * @brief Alias declaration for the most common use case.
- * @tparam Args Other template parameters.
- */
- template<typename... Args>
- using handle_view = basic_handle<entity, 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 entity, Args...>;
- /*! @brief Alias declaration for the most common use case. */
- using snapshot = basic_snapshot<entity>;
- /*! @brief Alias declaration for the most common use case. */
- using snapshot_loader = basic_snapshot_loader<entity>;
- /*! @brief Alias declaration for the most common use case. */
- using continuous_loader = basic_continuous_loader<entity>;
- /**
- * @brief Alias declaration for the most common use case.
- * @tparam Get Types of components iterated by the view.
- * @tparam Exclude Types of components used to filter the view.
- */
- template<typename Get, typename Exclude = exclude_t<>>
- using view = basic_view<entity, Get, Exclude>;
- /*! @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.
- * @tparam Args Other template parameters.
- */
- template<typename... Args>
- using group = basic_group<entity, Args...>;
- } // namespace entt
- #endif
- namespace entt {
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- 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>> {};
- template<typename Type>
- struct entt_traits<Type, std::enable_if_t<std::is_class_v<Type>>>
- : entt_traits<typename Type::entity_type> {};
- template<>
- struct entt_traits<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;
- static constexpr std::size_t entity_shift = 20u;
- };
- template<>
- struct entt_traits<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;
- static constexpr std::size_t entity_shift = 32u;
- };
- } // namespace internal
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /**
- * @brief Entity traits.
- * @tparam Type Type of identifier.
- */
- template<typename Type>
- class entt_traits: internal::entt_traits<Type> {
- using base_type = internal::entt_traits<Type>;
- public:
- /*! @brief Value type. */
- using value_type = Type;
- /*! @brief Underlying entity type. */
- using entity_type = typename base_type::entity_type;
- /*! @brief Underlying version type. */
- using version_type = typename base_type::version_type;
- /*! @brief Reserved identifier. */
- static constexpr entity_type reserved = base_type::entity_mask | (base_type::version_mask << base_type::entity_shift);
- /*! @brief Page size, default is `ENTT_SPARSE_PAGE`. */
- static constexpr auto page_size = ENTT_SPARSE_PAGE;
- /**
- * @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) ENTT_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) ENTT_NOEXCEPT {
- return (to_integral(value) & base_type::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) ENTT_NOEXCEPT {
- return (to_integral(value) >> base_type::entity_shift);
- }
- /**
- * @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) ENTT_NOEXCEPT {
- return value_type{(entity & base_type::entity_mask) | (static_cast<entity_type>(version) << base_type::entity_shift)};
- }
- /**
- * @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) ENTT_NOEXCEPT {
- constexpr auto mask = (base_type::version_mask << base_type::entity_shift);
- return value_type{(lhs & base_type::entity_mask) | (rhs & mask)};
- }
- };
- /**
- * @copydoc entt_traits<Entity>::to_integral
- * @tparam Entity The value type.
- */
- template<typename Entity>
- [[nodiscard]] constexpr typename entt_traits<Entity>::entity_type to_integral(const Entity value) ENTT_NOEXCEPT {
- return entt_traits<Entity>::to_integral(value);
- }
- /**
- * @copydoc entt_traits<Entity>::to_entity
- * @tparam Entity The value type.
- */
- template<typename Entity>
- [[nodiscard]] constexpr typename entt_traits<Entity>::entity_type to_entity(const Entity value) ENTT_NOEXCEPT {
- return entt_traits<Entity>::to_entity(value);
- }
- /**
- * @copydoc entt_traits<Entity>::to_version
- * @tparam Entity The value type.
- */
- template<typename Entity>
- [[nodiscard]] constexpr typename entt_traits<Entity>::version_type to_version(const Entity value) ENTT_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 ENTT_NOEXCEPT {
- using entity_traits = entt_traits<Entity>;
- return entity_traits::combine(entity_traits::reserved, entity_traits::reserved);
- }
- /**
- * @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 ENTT_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 ENTT_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 ENTT_NOEXCEPT {
- using entity_traits = entt_traits<Entity>;
- return entity_traits::to_entity(entity) == entity_traits::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 ENTT_NOEXCEPT {
- return !(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.
- * @param other 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 entity, const null_t other) ENTT_NOEXCEPT {
- return other.operator==(entity);
- }
- /**
- * @brief Compares a null object and an identifier of any type.
- * @tparam Entity Type of identifier.
- * @param entity Identifier with which to compare.
- * @param other 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 entity, const null_t other) ENTT_NOEXCEPT {
- return !(other == entity);
- }
- /*! @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 ENTT_NOEXCEPT {
- using entity_traits = entt_traits<Entity>;
- return entity_traits::combine(entity_traits::reserved, entity_traits::reserved);
- }
- /**
- * @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 ENTT_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 ENTT_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 ENTT_NOEXCEPT {
- using entity_traits = entt_traits<Entity>;
- return entity_traits::to_version(entity) == entity_traits::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 ENTT_NOEXCEPT {
- return !(entity == *this);
- }
- };
- /**
- * @brief Compares a tombstone object and an identifier of any type.
- * @tparam Entity Type of identifier.
- * @param entity Identifier with which to compare.
- * @param other 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 entity, const tombstone_t other) ENTT_NOEXCEPT {
- return other.operator==(entity);
- }
- /**
- * @brief Compares a tombstone object and an identifier of any type.
- * @tparam Entity Type of identifier.
- * @param entity Identifier with which to compare.
- * @param other 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 entity, const tombstone_t other) ENTT_NOEXCEPT {
- return !(other == entity);
- }
- /**
- * @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 <tuple>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- // #include "../core/iterator.hpp"
- #ifndef ENTT_CORE_ITERATOR_HPP
- #define ENTT_CORE_ITERATOR_HPP
- #include <iterator>
- #include <memory>
- #include <utility>
- // #include "../config/config.h"
- 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 Pointer type. */
- using pointer = Type *;
- /*! @brief Default copy constructor, deleted on purpose. */
- input_iterator_pointer(const input_iterator_pointer &) = delete;
- /*! @brief Default move constructor. */
- input_iterator_pointer(input_iterator_pointer &&) = default;
- /**
- * @brief Constructs a proxy object by move.
- * @param val Value to use to initialize the proxy object.
- */
- input_iterator_pointer(Type &&val)
- : value{std::move(val)} {}
- /**
- * @brief Default copy assignment operator, deleted on purpose.
- * @return This proxy object.
- */
- input_iterator_pointer &operator=(const input_iterator_pointer &) = delete;
- /**
- * @brief Default move assignment operator.
- * @return This proxy object.
- */
- input_iterator_pointer &operator=(input_iterator_pointer &&) = default;
- /**
- * @brief Access operator for accessing wrapped values.
- * @return A pointer to the wrapped value.
- */
- [[nodiscard]] pointer operator->() ENTT_NOEXCEPT {
- return std::addressof(value);
- }
- private:
- Type value;
- };
- /**
- * @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. */
- iterable_adaptor() = default;
- /**
- * @brief Creates an iterable object from a pair of iterators.
- * @param from Begin iterator.
- * @param to End iterator.
- */
- iterable_adaptor(iterator from, sentinel to)
- : first{from},
- last{to} {}
- /**
- * @brief Returns an iterator to the beginning.
- * @return An iterator to the first element of the range.
- */
- [[nodiscard]] iterator begin() const ENTT_NOEXCEPT {
- return first;
- }
- /**
- * @brief Returns an iterator to the end.
- * @return An iterator to the element following the last element of the
- * range.
- */
- [[nodiscard]] sentinel end() const ENTT_NOEXCEPT {
- return last;
- }
- /*! @copydoc begin */
- [[nodiscard]] iterator cbegin() const ENTT_NOEXCEPT {
- return begin();
- }
- /*! @copydoc end */
- [[nodiscard]] sentinel cend() const ENTT_NOEXCEPT {
- return end();
- }
- private:
- It first;
- Sentinel last;
- };
- } // namespace entt
- #endif
- // #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"
- namespace entt {
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- namespace internal {
- template<typename, typename = void>
- struct in_place_delete: 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, (ENTT_IGNORE_IF_EMPTY && std::is_empty_v<Type>) ? 0u : ENTT_PACKED_PAGE> {};
- template<typename Type>
- struct page_size<Type, std::enable_if_t<std::is_convertible_v<decltype(Type::page_size), std::size_t>>>
- : std::integral_constant<std::size_t, Type::page_size> {};
- } // namespace internal
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /**
- * @brief Common way to access various properties of components.
- * @tparam Type Type of component.
- */
- template<typename Type, typename = void>
- struct component_traits {
- static_assert(std::is_same_v<std::decay_t<Type>, Type>, "Unsupported type");
- /*! @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;
- };
- /**
- * @brief Helper variable template.
- * @tparam Type Type of component.
- */
- template<class Type>
- inline constexpr bool ignore_as_empty_v = (component_traits<Type>::page_size == 0u);
- } // namespace entt
- #endif
- // #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 "fwd.hpp"
- namespace entt {
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- 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>> {};
- template<typename Type>
- struct entt_traits<Type, std::enable_if_t<std::is_class_v<Type>>>
- : entt_traits<typename Type::entity_type> {};
- template<>
- struct entt_traits<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;
- static constexpr std::size_t entity_shift = 20u;
- };
- template<>
- struct entt_traits<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;
- static constexpr std::size_t entity_shift = 32u;
- };
- } // namespace internal
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /**
- * @brief Entity traits.
- * @tparam Type Type of identifier.
- */
- template<typename Type>
- class entt_traits: internal::entt_traits<Type> {
- using base_type = internal::entt_traits<Type>;
- public:
- /*! @brief Value type. */
- using value_type = Type;
- /*! @brief Underlying entity type. */
- using entity_type = typename base_type::entity_type;
- /*! @brief Underlying version type. */
- using version_type = typename base_type::version_type;
- /*! @brief Reserved identifier. */
- static constexpr entity_type reserved = base_type::entity_mask | (base_type::version_mask << base_type::entity_shift);
- /*! @brief Page size, default is `ENTT_SPARSE_PAGE`. */
- static constexpr auto page_size = ENTT_SPARSE_PAGE;
- /**
- * @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) ENTT_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) ENTT_NOEXCEPT {
- return (to_integral(value) & base_type::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) ENTT_NOEXCEPT {
- return (to_integral(value) >> base_type::entity_shift);
- }
- /**
- * @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) ENTT_NOEXCEPT {
- return value_type{(entity & base_type::entity_mask) | (static_cast<entity_type>(version) << base_type::entity_shift)};
- }
- /**
- * @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) ENTT_NOEXCEPT {
- constexpr auto mask = (base_type::version_mask << base_type::entity_shift);
- return value_type{(lhs & base_type::entity_mask) | (rhs & mask)};
- }
- };
- /**
- * @copydoc entt_traits<Entity>::to_integral
- * @tparam Entity The value type.
- */
- template<typename Entity>
- [[nodiscard]] constexpr typename entt_traits<Entity>::entity_type to_integral(const Entity value) ENTT_NOEXCEPT {
- return entt_traits<Entity>::to_integral(value);
- }
- /**
- * @copydoc entt_traits<Entity>::to_entity
- * @tparam Entity The value type.
- */
- template<typename Entity>
- [[nodiscard]] constexpr typename entt_traits<Entity>::entity_type to_entity(const Entity value) ENTT_NOEXCEPT {
- return entt_traits<Entity>::to_entity(value);
- }
- /**
- * @copydoc entt_traits<Entity>::to_version
- * @tparam Entity The value type.
- */
- template<typename Entity>
- [[nodiscard]] constexpr typename entt_traits<Entity>::version_type to_version(const Entity value) ENTT_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 ENTT_NOEXCEPT {
- using entity_traits = entt_traits<Entity>;
- return entity_traits::combine(entity_traits::reserved, entity_traits::reserved);
- }
- /**
- * @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 ENTT_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 ENTT_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 ENTT_NOEXCEPT {
- using entity_traits = entt_traits<Entity>;
- return entity_traits::to_entity(entity) == entity_traits::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 ENTT_NOEXCEPT {
- return !(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.
- * @param other 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 entity, const null_t other) ENTT_NOEXCEPT {
- return other.operator==(entity);
- }
- /**
- * @brief Compares a null object and an identifier of any type.
- * @tparam Entity Type of identifier.
- * @param entity Identifier with which to compare.
- * @param other 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 entity, const null_t other) ENTT_NOEXCEPT {
- return !(other == entity);
- }
- /*! @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 ENTT_NOEXCEPT {
- using entity_traits = entt_traits<Entity>;
- return entity_traits::combine(entity_traits::reserved, entity_traits::reserved);
- }
- /**
- * @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 ENTT_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 ENTT_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 ENTT_NOEXCEPT {
- using entity_traits = entt_traits<Entity>;
- return entity_traits::to_version(entity) == entity_traits::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 ENTT_NOEXCEPT {
- return !(entity == *this);
- }
- };
- /**
- * @brief Compares a tombstone object and an identifier of any type.
- * @tparam Entity Type of identifier.
- * @param entity Identifier with which to compare.
- * @param other 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 entity, const tombstone_t other) ENTT_NOEXCEPT {
- return other.operator==(entity);
- }
- /**
- * @brief Compares a tombstone object and an identifier of any type.
- * @tparam Entity Type of identifier.
- * @param entity Identifier with which to compare.
- * @param other 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 entity, const tombstone_t other) ENTT_NOEXCEPT {
- return !(other == entity);
- }
- /**
- * @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"
- // #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"
- #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 <utility>
- // #include "../config/config.h"
- 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<class Type>
- [[nodiscard]] constexpr Type &&operator()(Type &&value) const ENTT_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) ENTT_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) ENTT_NOEXCEPT {
- return func;
- }
- /**
- * @brief Helper type for visitors.
- * @tparam Func Types of function objects.
- */
- template<class... Func>
- struct overloaded: Func... {
- using Func::operator()...;
- };
- /**
- * @brief Deduction guide.
- * @tparam Func Types of function objects.
- */
- template<class... Func>
- overloaded(Func...) -> overloaded<Func...>;
- /**
- * @brief Basic implementation of a y-combinator.
- * @tparam Func Type of a potentially recursive function.
- */
- template<class Func>
- struct y_combinator {
- /**
- * @brief Constructs a y-combinator from a given function.
- * @param recursive A potentially recursive function.
- */
- y_combinator(Func recursive)
- : 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<class... Args>
- decltype(auto) operator()(Args &&...args) const {
- return func(*this, std::forward<Args>(args)...);
- }
- /*! @copydoc operator()() */
- template<class... Args>
- decltype(auto) operator()(Args &&...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;
- for(; pre > first && compare(value, *(pre - 1)); --pre) {
- *pre = std::move(*(pre - 1));
- }
- *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) {
- static constexpr auto mask = (1 << Bit) - 1;
- static constexpr auto buckets = 1 << Bit;
- static constexpr auto passes = N / Bit;
- using value_type = typename std::iterator_traits<It>::value_type;
- std::vector<value_type> aux(std::distance(first, last));
- auto part = [getter = std::move(getter)](auto from, auto to, auto out, auto start) {
- std::size_t index[buckets]{};
- std::size_t count[buckets]{};
- for(auto it = from; it != to; ++it) {
- ++count[(getter(*it) >> start) & mask];
- }
- 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) {
- out[index[(getter(*it) >> start) & mask]++] = std::move(*it);
- }
- };
- for(std::size_t pass = 0; pass < (passes & ~1); 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"
- // #include "../core/utility.hpp"
- #ifndef ENTT_CORE_UTILITY_HPP
- #define ENTT_CORE_UTILITY_HPP
- #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
- #define ENTT_STR(arg) #arg
- #define ENTT_XSTR(arg) ENTT_STR(arg)
- #endif
- #define ENTT_VERSION_MAJOR 3
- #define ENTT_VERSION_MINOR 10
- #define ENTT_VERSION_PATCH 3
- #define ENTT_VERSION \
- ENTT_XSTR(ENTT_VERSION_MAJOR) \
- "." ENTT_XSTR(ENTT_VERSION_MINOR) "." ENTT_XSTR(ENTT_VERSION_PATCH)
- #endif
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #ifndef ENTT_NOEXCEPT
- # define ENTT_NOEXCEPT noexcept
- # define ENTT_NOEXCEPT_IF(expr) noexcept(expr)
- # else
- # define ENTT_NOEXCEPT_IF(...)
- #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
- #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(...) (void(0))
- #elif !defined ENTT_ASSERT
- # include <cassert>
- # define ENTT_ASSERT(condition, ...) assert(condition)
- #endif
- #ifdef ENTT_NO_ETO
- # define ENTT_IGNORE_IF_EMPTY false
- #else
- # define ENTT_IGNORE_IF_EMPTY true
- #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
- #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
- #endif
- 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<class Type>
- [[nodiscard]] constexpr Type &&operator()(Type &&value) const ENTT_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) ENTT_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) ENTT_NOEXCEPT {
- return func;
- }
- /**
- * @brief Helper type for visitors.
- * @tparam Func Types of function objects.
- */
- template<class... Func>
- struct overloaded: Func... {
- using Func::operator()...;
- };
- /**
- * @brief Deduction guide.
- * @tparam Func Types of function objects.
- */
- template<class... Func>
- overloaded(Func...) -> overloaded<Func...>;
- /**
- * @brief Basic implementation of a y-combinator.
- * @tparam Func Type of a potentially recursive function.
- */
- template<class Func>
- struct y_combinator {
- /**
- * @brief Constructs a y-combinator from a given function.
- * @param recursive A potentially recursive function.
- */
- y_combinator(Func recursive)
- : 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<class... Args>
- decltype(auto) operator()(Args &&...args) const {
- return func(*this, std::forward<Args>(args)...);
- }
- /*! @copydoc operator()() */
- template<class... Args>
- decltype(auto) operator()(Args &&...args) {
- return func(*this, std::forward<Args>(args)...);
- }
- private:
- Func func;
- };
- } // namespace entt
- #endif
- // #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 "../core/attribute.h"
- #ifndef ENTT_CORE_ATTRIBUTE_H
- #define ENTT_CORE_ATTRIBUTE_H
- #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
- #endif
- // #include "fwd.hpp"
- // #include "hashed_string.hpp"
- #ifndef ENTT_CORE_HASHED_STRING_HPP
- #define ENTT_CORE_HASHED_STRING_HPP
- #include <cstddef>
- #include <cstdint>
- // #include "../config/config.h"
- // #include "fwd.hpp"
- namespace entt {
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- namespace internal {
- template<typename>
- struct fnv1a_traits;
- template<>
- struct fnv1a_traits<std::uint32_t> {
- using type = std::uint32_t;
- static constexpr std::uint32_t offset = 2166136261;
- static constexpr std::uint32_t prime = 16777619;
- };
- template<>
- struct fnv1a_traits<std::uint64_t> {
- using type = std::uint64_t;
- static constexpr std::uint64_t offset = 14695981039346656037ull;
- static constexpr std::uint64_t 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;
- size_type length;
- hash_type hash;
- };
- } // namespace internal
- /**
- * Internal details not to be documented.
- * @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 hs_traits = internal::fnv1a_traits<id_type>;
- struct const_wrapper {
- // non-explicit constructor on purpose
- constexpr const_wrapper(const Char *str) ENTT_NOEXCEPT: repr{str} {}
- const Char *repr;
- };
- // Fowler–Noll–Vo hash function v. 1a - the good
- [[nodiscard]] static constexpr auto helper(const Char *str) ENTT_NOEXCEPT {
- base_type base{str, 0u, hs_traits::offset};
- for(; str[base.length]; ++base.length) {
- base.hash = (base.hash ^ static_cast<hs_traits::type>(str[base.length])) * hs_traits::prime;
- }
- return base;
- }
- // Fowler–Noll–Vo hash function v. 1a - the good
- [[nodiscard]] static constexpr auto helper(const Char *str, const std::size_t len) ENTT_NOEXCEPT {
- base_type base{str, len, hs_traits::offset};
- for(size_type pos{}; pos < len; ++pos) {
- base.hash = (base.hash ^ static_cast<hs_traits::type>(str[pos])) * hs_traits::prime;
- }
- return base;
- }
- 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) ENTT_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>
- [[nodiscard]] static constexpr hash_type value(const value_type (&str)[N]) ENTT_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) ENTT_NOEXCEPT {
- return basic_hashed_string{wrapper};
- }
- /*! @brief Constructs an empty hashed string. */
- constexpr basic_hashed_string() ENTT_NOEXCEPT
- : base_type{} {}
- /**
- * @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) ENTT_NOEXCEPT
- : base_type{helper(str, len)} {}
- /**
- * @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>
- constexpr basic_hashed_string(const value_type (&str)[N]) ENTT_NOEXCEPT
- : base_type{helper(str)} {}
- /**
- * @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) ENTT_NOEXCEPT
- : base_type{helper(wrapper.repr)} {}
- /**
- * @brief Returns the size a hashed string.
- * @return The size of the hashed string.
- */
- [[nodiscard]] constexpr size_type size() const ENTT_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 ENTT_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 ENTT_NOEXCEPT {
- return base_type::hash;
- }
- /*! @copydoc data */
- [[nodiscard]] constexpr operator const value_type *() const ENTT_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 ENTT_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, const 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>
- 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) ENTT_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) ENTT_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) ENTT_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) ENTT_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) ENTT_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) ENTT_NOEXCEPT {
- return !(lhs < rhs);
- }
- /*! @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>;
- inline namespace literals {
- /**
- * @brief User defined literal for hashed strings.
- * @param str The literal without its suffix.
- * @return A properly initialized hashed string.
- */
- [[nodiscard]] constexpr hashed_string operator"" _hs(const char *str, std::size_t) ENTT_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]] constexpr hashed_wstring operator"" _hws(const wchar_t *str, std::size_t) ENTT_NOEXCEPT {
- return hashed_wstring{str};
- }
- } // namespace literals
- } // namespace entt
- #endif
- namespace entt {
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- namespace internal {
- struct ENTT_API type_index final {
- [[nodiscard]] static id_type next() ENTT_NOEXCEPT {
- static ENTT_MAYBE_ATOMIC(id_type) value{};
- return value++;
- }
- };
- template<typename Type>
- [[nodiscard]] constexpr auto stripped_type_name() ENTT_NOEXCEPT {
- #if defined ENTT_PRETTY_FUNCTION
- std::string_view pretty_function{ENTT_PRETTY_FUNCTION};
- auto first = pretty_function.find_first_not_of(' ', pretty_function.find_first_of(ENTT_PRETTY_FUNCTION_PREFIX) + 1);
- auto value = pretty_function.substr(first, pretty_function.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]] static constexpr std::string_view type_name(int) ENTT_NOEXCEPT {
- constexpr auto value = stripped_type_name<Type>();
- return value;
- }
- template<typename Type>
- [[nodiscard]] static std::string_view type_name(char) ENTT_NOEXCEPT {
- static const auto value = stripped_type_name<Type>();
- return value;
- }
- template<typename Type, auto = stripped_type_name<Type>().find_first_of('.')>
- [[nodiscard]] static constexpr id_type type_hash(int) ENTT_NOEXCEPT {
- constexpr auto stripped = stripped_type_name<Type>();
- constexpr auto value = hashed_string::value(stripped.data(), stripped.size());
- return value;
- }
- template<typename Type>
- [[nodiscard]] static id_type type_hash(char) ENTT_NOEXCEPT {
- static const auto value = [](const auto stripped) {
- return hashed_string::value(stripped.data(), stripped.size());
- }(stripped_type_name<Type>());
- return value;
- }
- } // namespace internal
- /**
- * Internal details not to be documented.
- * @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() ENTT_NOEXCEPT {
- static const id_type value = internal::type_index::next();
- return value;
- }
- /*! @copydoc value */
- [[nodiscard]] constexpr operator id_type() const ENTT_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() ENTT_NOEXCEPT {
- return internal::type_hash<Type>(0);
- #else
- [[nodiscard]] static constexpr id_type value() ENTT_NOEXCEPT {
- return type_index<Type>::value();
- #endif
- }
- /*! @copydoc value */
- [[nodiscard]] constexpr operator id_type() const ENTT_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() ENTT_NOEXCEPT {
- return internal::type_name<Type>(0);
- }
- /*! @copydoc value */
- [[nodiscard]] constexpr operator std::string_view() const ENTT_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>
- constexpr type_info(std::in_place_type_t<Type>) ENTT_NOEXCEPT
- : seq{type_index<std::remove_cv_t<std::remove_reference_t<Type>>>::value()},
- identifier{type_hash<std::remove_cv_t<std::remove_reference_t<Type>>>::value()},
- alias{type_name<std::remove_cv_t<std::remove_reference_t<Type>>>::value()} {}
- /**
- * @brief Type index.
- * @return Type index.
- */
- [[nodiscard]] constexpr id_type index() const ENTT_NOEXCEPT {
- return seq;
- }
- /**
- * @brief Type hash.
- * @return Type hash.
- */
- [[nodiscard]] constexpr id_type hash() const ENTT_NOEXCEPT {
- return identifier;
- }
- /**
- * @brief Type name.
- * @return Type name.
- */
- [[nodiscard]] constexpr std::string_view name() const ENTT_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]] inline constexpr bool operator==(const type_info &lhs, const type_info &rhs) ENTT_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]] inline constexpr bool operator!=(const type_info &lhs, const type_info &rhs) ENTT_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) ENTT_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) ENTT_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) ENTT_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) ENTT_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() ENTT_NOEXCEPT {
- if constexpr(std::is_same_v<Type, std::remove_cv_t<std::remove_reference_t<Type>>>) {
- static type_info instance{std::in_place_type<Type>};
- return instance;
- } else {
- return type_id<std::remove_cv_t<std::remove_reference_t<Type>>>();
- }
- }
- /*! @copydoc type_id */
- template<typename Type>
- [[nodiscard]] const type_info &type_id(Type &&) ENTT_NOEXCEPT {
- return type_id<std::remove_cv_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 <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.
- * @tparam The size of the type if `sizeof` accepts it, 0 otherwise.
- */
- 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))>>
- : 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 Type First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<std::size_t Index, typename Type, typename... Other>
- struct type_list_element<Index, type_list<Type, Other...>>
- : type_list_element<Index - 1u, type_list<Other...>> {};
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam Type First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<typename Type, typename... Other>
- struct type_list_element<0u, type_list<Type, Other...>> {
- /*! @brief Searched type. */
- using type = Type;
- };
- /**
- * @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 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;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename>
- struct type_list_unique;
- /**
- * @brief Removes duplicates types from a type list.
- * @tparam Type One of the types provided by the given type list.
- * @tparam Other The other types provided by the given type list.
- */
- template<typename Type, typename... Other>
- struct type_list_unique<type_list<Type, Other...>> {
- /*! @brief A type list without duplicate types. */
- using type = std::conditional_t<
- (std::is_same_v<Type, Other> || ...),
- typename type_list_unique<type_list<Other...>>::type,
- type_list_cat_t<type_list<Type>, typename type_list_unique<type_list<Other...>>::type>>;
- };
- /*! @brief Removes duplicates types from a type list. */
- template<>
- struct type_list_unique<type_list<>> {
- /*! @brief A type list without duplicate types. */
- using type = type_list<>;
- };
- /**
- * @brief Helper type.
- * @tparam Type A type list.
- */
- template<typename Type>
- using type_list_unique_t = typename type_list_unique<Type>::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::disjunction<std::is_same<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 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 value. */
- static constexpr auto value = Value;
- };
- /**
- * @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 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 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
- * Internal details not to be documented.
- */
- 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
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /*! @copydoc is_iterator */
- template<typename Type>
- struct is_iterator<Type, std::enable_if_t<!std::is_same_v<std::remove_const_t<std::remove_pointer_t<Type>>, void>>>
- : 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::conjunction<std::is_empty<Type>, std::negation<std::is_final<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;
- /**
- * @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, typename = void>
- struct is_equality_comparable: std::false_type {};
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- 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 Type, std::size_t... Index>
- [[nodiscard]] constexpr bool unpack_maybe_equality_comparable(std::index_sequence<Index...>) {
- return (is_equality_comparable<std::tuple_element_t<Index, Type>>::value && ...);
- }
- template<typename>
- [[nodiscard]] constexpr bool maybe_equality_comparable(choice_t<0>) {
- return true;
- }
- template<typename Type>
- [[nodiscard]] constexpr auto maybe_equality_comparable(choice_t<1>) -> decltype(std::declval<typename Type::value_type>(), bool{}) {
- if constexpr(is_iterator_v<Type>) {
- return true;
- } else if constexpr(std::is_same_v<typename Type::value_type, Type>) {
- return maybe_equality_comparable<Type>(choice<0>);
- } else {
- return is_equality_comparable<typename Type::value_type>::value;
- }
- }
- template<typename Type>
- [[nodiscard]] constexpr std::enable_if_t<is_complete_v<std::tuple_size<std::remove_const_t<Type>>>, bool> maybe_equality_comparable(choice_t<2>) {
- if constexpr(has_tuple_size_value<Type>::value) {
- return unpack_maybe_equality_comparable<Type>(std::make_index_sequence<std::tuple_size<Type>::value>{});
- } else {
- return maybe_equality_comparable<Type>(choice<1>);
- }
- }
- } // namespace internal
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /*! @copydoc is_equality_comparable */
- template<typename Type>
- struct is_equality_comparable<Type, std::void_t<decltype(std::declval<Type>() == std::declval<Type>())>>
- : std::bool_constant<internal::maybe_equality_comparable<Type>(choice<2>)> {};
- /**
- * @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 = std::add_const_t<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;
- } // namespace entt
- #endif
- namespace entt {
- /**
- * @brief A SBO friendly, type-safe container for single values of any type.
- * @tparam Len Size of the storage reserved for the small buffer optimization.
- * @tparam Align Optional alignment requirement.
- */
- template<std::size_t Len, std::size_t Align>
- class basic_any {
- enum class operation : std::uint8_t {
- copy,
- move,
- transfer,
- assign,
- destroy,
- compare,
- get
- };
- enum class policy : std::uint8_t {
- owner,
- ref,
- cref
- };
- using storage_type = std::aligned_storage_t<Len + !Len, Align>;
- using vtable_type = const void *(const operation, const basic_any &, const void *);
- template<typename Type>
- static constexpr bool in_situ = Len && alignof(Type) <= alignof(storage_type) && sizeof(Type) <= sizeof(storage_type) && std::is_nothrow_move_constructible_v<Type>;
- template<typename Type>
- static const void *basic_vtable([[maybe_unused]] const operation op, [[maybe_unused]] const basic_any &value, [[maybe_unused]] const void *other) {
- static_assert(!std::is_same_v<Type, void> && std::is_same_v<std::remove_cv_t<std::remove_reference_t<Type>>, Type>, "Invalid type");
- const Type *element = nullptr;
- if constexpr(in_situ<Type>) {
- element = value.owner() ? reinterpret_cast<const Type *>(&value.storage) : static_cast<const Type *>(value.instance);
- } else {
- element = static_cast<const Type *>(value.instance);
- }
- switch(op) {
- case operation::copy:
- if constexpr(std::is_copy_constructible_v<Type>) {
- static_cast<basic_any *>(const_cast<void *>(other))->initialize<Type>(*element);
- }
- break;
- case operation::move:
- if constexpr(in_situ<Type>) {
- if(value.owner()) {
- return new(&static_cast<basic_any *>(const_cast<void *>(other))->storage) Type{std::move(*const_cast<Type *>(element))};
- }
- }
- return (static_cast<basic_any *>(const_cast<void *>(other))->instance = std::exchange(const_cast<basic_any &>(value).instance, nullptr));
- case operation::transfer:
- if constexpr(std::is_move_assignable_v<Type>) {
- *const_cast<Type *>(element) = std::move(*static_cast<Type *>(const_cast<void *>(other)));
- return other;
- }
- [[fallthrough]];
- case operation::assign:
- if constexpr(std::is_copy_assignable_v<Type>) {
- *const_cast<Type *>(element) = *static_cast<const Type *>(other);
- return other;
- }
- break;
- case operation::destroy:
- if constexpr(in_situ<Type>) {
- element->~Type();
- } else if constexpr(std::is_array_v<Type>) {
- delete[] element;
- } else {
- delete element;
- }
- break;
- case operation::compare:
- if constexpr(!std::is_function_v<Type> && !std::is_array_v<Type> && is_equality_comparable_v<Type>) {
- return *static_cast<const Type *>(element) == *static_cast<const Type *>(other) ? other : nullptr;
- } else {
- return (element == other) ? other : nullptr;
- }
- case operation::get:
- return element;
- }
- return nullptr;
- }
- template<typename Type, typename... Args>
- void initialize([[maybe_unused]] Args &&...args) {
- if constexpr(!std::is_void_v<Type>) {
- info = &type_id<std::remove_cv_t<std::remove_reference_t<Type>>>();
- vtable = basic_vtable<std::remove_cv_t<std::remove_reference_t<Type>>>;
- if constexpr(std::is_lvalue_reference_v<Type>) {
- static_assert(sizeof...(Args) == 1u && (std::is_lvalue_reference_v<Args> && ...), "Invalid arguments");
- mode = std::is_const_v<std::remove_reference_t<Type>> ? policy::cref : policy::ref;
- instance = (std::addressof(args), ...);
- } else if constexpr(in_situ<Type>) {
- if constexpr(sizeof...(Args) != 0u && std::is_aggregate_v<Type>) {
- new(&storage) Type{std::forward<Args>(args)...};
- } else {
- new(&storage) Type(std::forward<Args>(args)...);
- }
- } else {
- if constexpr(sizeof...(Args) != 0u && std::is_aggregate_v<Type>) {
- instance = new Type{std::forward<Args>(args)...};
- } else {
- instance = new Type(std::forward<Args>(args)...);
- }
- }
- }
- }
- basic_any(const basic_any &other, const policy pol) ENTT_NOEXCEPT
- : instance{other.data()},
- info{other.info},
- vtable{other.vtable},
- mode{pol} {}
- public:
- /*! @brief Size of the internal storage. */
- static constexpr auto length = Len;
- /*! @brief Alignment requirement. */
- static constexpr auto alignment = Align;
- /*! @brief Default constructor. */
- constexpr basic_any() ENTT_NOEXCEPT
- : instance{},
- info{&type_id<void>()},
- vtable{},
- mode{policy::owner} {}
- /**
- * @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)
- : basic_any{} {
- initialize<Type>(std::forward<Args>(args)...);
- }
- /**
- * @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{} {
- initialize<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{} {
- if(other.vtable) {
- other.vtable(operation::copy, other, this);
- }
- }
- /**
- * @brief Move constructor.
- * @param other The instance to move from.
- */
- basic_any(basic_any &&other) ENTT_NOEXCEPT
- : instance{},
- info{other.info},
- vtable{other.vtable},
- mode{other.mode} {
- if(other.vtable) {
- other.vtable(operation::move, other, this);
- }
- }
- /*! @brief Frees the internal storage, whatever it means. */
- ~basic_any() {
- if(vtable && owner()) {
- vtable(operation::destroy, *this, nullptr);
- }
- }
- /**
- * @brief Copy assignment operator.
- * @param other The instance to copy from.
- * @return This any object.
- */
- basic_any &operator=(const basic_any &other) {
- reset();
- if(other.vtable) {
- other.vtable(operation::copy, other, this);
- }
- return *this;
- }
- /**
- * @brief Move assignment operator.
- * @param other The instance to move from.
- * @return This any object.
- */
- basic_any &operator=(basic_any &&other) ENTT_NOEXCEPT {
- reset();
- if(other.vtable) {
- other.vtable(operation::move, other, this);
- info = other.info;
- vtable = other.vtable;
- 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>
- 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 the object type if any, `type_id<void>()` otherwise.
- * @return The object type if any, `type_id<void>()` otherwise.
- */
- [[nodiscard]] const type_info &type() const ENTT_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 ENTT_NOEXCEPT {
- return vtable ? vtable(operation::get, *this, nullptr) : nullptr;
- }
- /**
- * @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 ENTT_NOEXCEPT {
- return *info == req ? data() : nullptr;
- }
- /**
- * @brief Returns an opaque pointer to the contained instance.
- * @return An opaque pointer the contained instance, if any.
- */
- [[nodiscard]] void *data() ENTT_NOEXCEPT {
- return (!vtable || mode == policy::cref) ? nullptr : const_cast<void *>(vtable(operation::get, *this, nullptr));
- }
- /**
- * @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) ENTT_NOEXCEPT {
- return *info == req ? data() : nullptr;
- }
- /**
- * @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) {
- reset();
- 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 any &other) {
- if(vtable && mode != policy::cref && *info == *other.info) {
- return (vtable(operation::assign, *this, other.data()) != nullptr);
- }
- return false;
- }
- /*! @copydoc assign */
- bool assign(any &&other) {
- if(vtable && mode != policy::cref && *info == *other.info) {
- if(auto *val = other.data(); val) {
- return (vtable(operation::transfer, *this, val) != nullptr);
- } else {
- return (vtable(operation::assign, *this, std::as_const(other).data()) != nullptr);
- }
- }
- return false;
- }
- /*! @brief Destroys contained object */
- void reset() {
- if(vtable && owner()) {
- vtable(operation::destroy, *this, nullptr);
- }
- info = &type_id<void>();
- vtable = nullptr;
- mode = policy::owner;
- }
- /**
- * @brief Returns false if a wrapper is empty, true otherwise.
- * @return False if the wrapper is empty, true otherwise.
- */
- [[nodiscard]] explicit operator bool() const ENTT_NOEXCEPT {
- return vtable != nullptr;
- }
- /**
- * @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.
- */
- bool operator==(const basic_any &other) const ENTT_NOEXCEPT {
- if(vtable && *info == *other.info) {
- return (vtable(operation::compare, *this, other.data()) != nullptr);
- }
- return (!vtable && !other.vtable);
- }
- /**
- * @brief Aliasing constructor.
- * @return A wrapper that shares a reference to an unmanaged object.
- */
- [[nodiscard]] basic_any as_ref() ENTT_NOEXCEPT {
- return basic_any{*this, (mode == policy::cref ? policy::cref : policy::ref)};
- }
- /*! @copydoc as_ref */
- [[nodiscard]] basic_any as_ref() const ENTT_NOEXCEPT {
- return basic_any{*this, policy::cref};
- }
- /**
- * @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 ENTT_NOEXCEPT {
- return (mode == policy::owner);
- }
- private:
- union {
- const void *instance;
- storage_type storage;
- };
- const type_info *info;
- vtable_type *vtable;
- policy mode;
- };
- /**
- * @brief Checks if two wrappers differ in their content.
- * @tparam Len Size of the storage reserved for the small buffer optimization.
- * @tparam Align Alignment requirement.
- * @param lhs A wrapper, either empty or not.
- * @param rhs A wrapper, either empty or not.
- * @return True if the two wrappers differ in their content, false otherwise.
- */
- template<std::size_t Len, std::size_t Align>
- [[nodiscard]] inline bool operator!=(const basic_any<Len, Align> &lhs, const basic_any<Len, Align> &rhs) ENTT_NOEXCEPT {
- return !(lhs == rhs);
- }
- /**
- * @brief Performs type-safe access to the contained object.
- * @tparam Type Type to which conversion is required.
- * @tparam Len Size of the storage 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>
- Type any_cast(const basic_any<Len, Align> &data) ENTT_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>
- Type any_cast(basic_any<Len, Align> &data) ENTT_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>
- Type any_cast(basic_any<Len, Align> &&data) ENTT_NOEXCEPT {
- if constexpr(std::is_copy_constructible_v<std::remove_cv_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));
- } else {
- 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>
- const Type *any_cast(const basic_any<Len, Align> *data) ENTT_NOEXCEPT {
- const auto &info = type_id<std::remove_cv_t<std::remove_reference_t<Type>>>();
- return static_cast<const Type *>(data->data(info));
- }
- /*! @copydoc any_cast */
- template<typename Type, std::size_t Len, std::size_t Align>
- Type *any_cast(basic_any<Len, Align> *data) ENTT_NOEXCEPT {
- const auto &info = type_id<std::remove_cv_t<std::remove_reference_t<Type>>>();
- // last attempt to make wrappers for const references return their values
- return static_cast<Type *>(static_cast<constness_as_t<basic_any<Len, Align>, Type> *>(data)->data(info));
- }
- /**
- * @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 storage 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>
- 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 storage 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>
- basic_any<Len, Align> forward_as_any(Type &&value) {
- return basic_any<Len, Align>{std::in_place_type<std::conditional_t<std::is_rvalue_reference_v<Type>, std::decay_t<Type>, Type>>, std::forward<Type>(value)};
- }
- } // namespace entt
- #endif
- // #include "../core/memory.hpp"
- #ifndef ENTT_CORE_MEMORY_HPP
- #define ENTT_CORE_MEMORY_HPP
- #include <cstddef>
- #include <limits>
- #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) ENTT_NOEXCEPT {
- if constexpr(std::is_pointer_v<std::remove_cv_t<std::remove_reference_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) ENTT_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) ENTT_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) ENTT_NOEXCEPT {
- ENTT_ASSERT(std::allocator_traits<Allocator>::propagate_on_container_swap::value || lhs == rhs, "Cannot swap the containers");
- if constexpr(std::allocator_traits<Allocator>::propagate_on_container_swap::value) {
- using std::swap;
- swap(lhs, rhs);
- }
- }
- /**
- * @brief Checks whether a value is a power of two or not.
- * @param value A value that may or may not be a power of two.
- * @return True if the value is a power of two, false otherwise.
- */
- [[nodiscard]] inline constexpr bool is_power_of_two(const std::size_t value) ENTT_NOEXCEPT {
- return value && ((value & (value - 1)) == 0);
- }
- /**
- * @brief Computes the smallest power of two greater than or equal to a value.
- * @param value The value to use.
- * @return The smallest power of two greater than or equal to the given value.
- */
- [[nodiscard]] inline constexpr std::size_t next_power_of_two(const std::size_t value) ENTT_NOEXCEPT {
- ENTT_ASSERT(value < (std::size_t{1u} << (std::numeric_limits<std::size_t>::digits - 1)), "Numeric limits exceeded");
- std::size_t curr = value - (value != 0u);
- for(int next = 1; next < std::numeric_limits<std::size_t>::digits; next = next * 2) {
- curr |= curr >> next;
- }
- return ++curr;
- }
- /**
- * @brief Fast module utility function (powers of two only).
- * @param value A value for which to calculate the modulus.
- * @param mod _Modulus_, it must be a power of two.
- * @return The common remainder.
- */
- [[nodiscard]] inline constexpr std::size_t fast_mod(const std::size_t value, const std::size_t mod) ENTT_NOEXCEPT {
- ENTT_ASSERT(is_power_of_two(mod), "Value must be a power of two");
- return value & (mod - 1u);
- }
- /**
- * @brief Deleter for allocator-aware unique pointers (waiting for C++20).
- * @tparam Args Types of arguments to use to construct the object.
- */
- 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.
- */
- allocation_deleter(const allocator_type &alloc)
- : Allocator{alloc} {}
- /**
- * @brief Destroys the pointed object and deallocates its memory.
- * @param ptr A valid pointer to an object of the given type.
- */
- void operator()(pointer ptr) {
- using alloc_traits = typename 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>
- 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
- * Internal details not to be documented.
- */
- 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) ENTT_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) ENTT_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) ENTT_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) ENTT_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) ENTT_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) ENTT_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
- /**
- * Internal details not to be documented.
- * @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) ENTT_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([&](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"
- #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 "../core/attribute.h"
- // #include "fwd.hpp"
- // #include "hashed_string.hpp"
- namespace entt {
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- namespace internal {
- struct ENTT_API type_index final {
- [[nodiscard]] static id_type next() ENTT_NOEXCEPT {
- static ENTT_MAYBE_ATOMIC(id_type) value{};
- return value++;
- }
- };
- template<typename Type>
- [[nodiscard]] constexpr auto stripped_type_name() ENTT_NOEXCEPT {
- #if defined ENTT_PRETTY_FUNCTION
- std::string_view pretty_function{ENTT_PRETTY_FUNCTION};
- auto first = pretty_function.find_first_not_of(' ', pretty_function.find_first_of(ENTT_PRETTY_FUNCTION_PREFIX) + 1);
- auto value = pretty_function.substr(first, pretty_function.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]] static constexpr std::string_view type_name(int) ENTT_NOEXCEPT {
- constexpr auto value = stripped_type_name<Type>();
- return value;
- }
- template<typename Type>
- [[nodiscard]] static std::string_view type_name(char) ENTT_NOEXCEPT {
- static const auto value = stripped_type_name<Type>();
- return value;
- }
- template<typename Type, auto = stripped_type_name<Type>().find_first_of('.')>
- [[nodiscard]] static constexpr id_type type_hash(int) ENTT_NOEXCEPT {
- constexpr auto stripped = stripped_type_name<Type>();
- constexpr auto value = hashed_string::value(stripped.data(), stripped.size());
- return value;
- }
- template<typename Type>
- [[nodiscard]] static id_type type_hash(char) ENTT_NOEXCEPT {
- static const auto value = [](const auto stripped) {
- return hashed_string::value(stripped.data(), stripped.size());
- }(stripped_type_name<Type>());
- return value;
- }
- } // namespace internal
- /**
- * Internal details not to be documented.
- * @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() ENTT_NOEXCEPT {
- static const id_type value = internal::type_index::next();
- return value;
- }
- /*! @copydoc value */
- [[nodiscard]] constexpr operator id_type() const ENTT_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() ENTT_NOEXCEPT {
- return internal::type_hash<Type>(0);
- #else
- [[nodiscard]] static constexpr id_type value() ENTT_NOEXCEPT {
- return type_index<Type>::value();
- #endif
- }
- /*! @copydoc value */
- [[nodiscard]] constexpr operator id_type() const ENTT_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() ENTT_NOEXCEPT {
- return internal::type_name<Type>(0);
- }
- /*! @copydoc value */
- [[nodiscard]] constexpr operator std::string_view() const ENTT_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>
- constexpr type_info(std::in_place_type_t<Type>) ENTT_NOEXCEPT
- : seq{type_index<std::remove_cv_t<std::remove_reference_t<Type>>>::value()},
- identifier{type_hash<std::remove_cv_t<std::remove_reference_t<Type>>>::value()},
- alias{type_name<std::remove_cv_t<std::remove_reference_t<Type>>>::value()} {}
- /**
- * @brief Type index.
- * @return Type index.
- */
- [[nodiscard]] constexpr id_type index() const ENTT_NOEXCEPT {
- return seq;
- }
- /**
- * @brief Type hash.
- * @return Type hash.
- */
- [[nodiscard]] constexpr id_type hash() const ENTT_NOEXCEPT {
- return identifier;
- }
- /**
- * @brief Type name.
- * @return Type name.
- */
- [[nodiscard]] constexpr std::string_view name() const ENTT_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]] inline constexpr bool operator==(const type_info &lhs, const type_info &rhs) ENTT_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]] inline constexpr bool operator!=(const type_info &lhs, const type_info &rhs) ENTT_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) ENTT_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) ENTT_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) ENTT_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) ENTT_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() ENTT_NOEXCEPT {
- if constexpr(std::is_same_v<Type, std::remove_cv_t<std::remove_reference_t<Type>>>) {
- static type_info instance{std::in_place_type<Type>};
- return instance;
- } else {
- return type_id<std::remove_cv_t<std::remove_reference_t<Type>>>();
- }
- }
- /*! @copydoc type_id */
- template<typename Type>
- [[nodiscard]] const type_info &type_id(Type &&) ENTT_NOEXCEPT {
- return type_id<std::remove_cv_t<std::remove_reference_t<Type>>>();
- }
- } // namespace entt
- #endif
- // #include "entity.hpp"
- // #include "fwd.hpp"
- namespace entt {
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- 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;
- sparse_set_iterator() ENTT_NOEXCEPT
- : packed{},
- offset{} {}
- sparse_set_iterator(const Container &ref, const difference_type idx) ENTT_NOEXCEPT
- : packed{std::addressof(ref)},
- offset{idx} {}
- sparse_set_iterator &operator++() ENTT_NOEXCEPT {
- return --offset, *this;
- }
- sparse_set_iterator operator++(int) ENTT_NOEXCEPT {
- sparse_set_iterator orig = *this;
- return ++(*this), orig;
- }
- sparse_set_iterator &operator--() ENTT_NOEXCEPT {
- return ++offset, *this;
- }
- sparse_set_iterator operator--(int) ENTT_NOEXCEPT {
- sparse_set_iterator orig = *this;
- return operator--(), orig;
- }
- sparse_set_iterator &operator+=(const difference_type value) ENTT_NOEXCEPT {
- offset -= value;
- return *this;
- }
- sparse_set_iterator operator+(const difference_type value) const ENTT_NOEXCEPT {
- sparse_set_iterator copy = *this;
- return (copy += value);
- }
- sparse_set_iterator &operator-=(const difference_type value) ENTT_NOEXCEPT {
- return (*this += -value);
- }
- sparse_set_iterator operator-(const difference_type value) const ENTT_NOEXCEPT {
- return (*this + -value);
- }
- [[nodiscard]] reference operator[](const difference_type value) const ENTT_NOEXCEPT {
- return packed->data()[index() - value];
- }
- [[nodiscard]] pointer operator->() const ENTT_NOEXCEPT {
- return packed->data() + index();
- }
- [[nodiscard]] reference operator*() const ENTT_NOEXCEPT {
- return *operator->();
- }
- [[nodiscard]] difference_type index() const ENTT_NOEXCEPT {
- return offset - 1;
- }
- private:
- const Container *packed;
- difference_type offset;
- };
- template<typename Type, typename Other>
- [[nodiscard]] std::ptrdiff_t operator-(const sparse_set_iterator<Type> &lhs, const sparse_set_iterator<Other> &rhs) ENTT_NOEXCEPT {
- return rhs.index() - lhs.index();
- }
- template<typename Type, typename Other>
- [[nodiscard]] bool operator==(const sparse_set_iterator<Type> &lhs, const sparse_set_iterator<Other> &rhs) ENTT_NOEXCEPT {
- return lhs.index() == rhs.index();
- }
- template<typename Type, typename Other>
- [[nodiscard]] bool operator!=(const sparse_set_iterator<Type> &lhs, const sparse_set_iterator<Other> &rhs) ENTT_NOEXCEPT {
- return !(lhs == rhs);
- }
- template<typename Type, typename Other>
- [[nodiscard]] bool operator<(const sparse_set_iterator<Type> &lhs, const sparse_set_iterator<Other> &rhs) ENTT_NOEXCEPT {
- return lhs.index() > rhs.index();
- }
- template<typename Type, typename Other>
- [[nodiscard]] bool operator>(const sparse_set_iterator<Type> &lhs, const sparse_set_iterator<Other> &rhs) ENTT_NOEXCEPT {
- return lhs.index() < rhs.index();
- }
- template<typename Type, typename Other>
- [[nodiscard]] bool operator<=(const sparse_set_iterator<Type> &lhs, const sparse_set_iterator<Other> &rhs) ENTT_NOEXCEPT {
- return !(lhs > rhs);
- }
- template<typename Type, typename Other>
- [[nodiscard]] bool operator>=(const sparse_set_iterator<Type> &lhs, const sparse_set_iterator<Other> &rhs) ENTT_NOEXCEPT {
- return !(lhs < rhs);
- }
- } // namespace internal
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /*! @brief Sparse set 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 Basic 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 is largely used by the registry to offer users the fastest access ever
- * to the components. Views and groups in general are almost entirely designed
- * around sparse sets.
- *
- * 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 (see entt_traits for more details).
- * @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 entity_traits = entt_traits<Entity>;
- [[nodiscard]] auto sparse_ptr(const Entity entt) const {
- const auto pos = static_cast<size_type>(entity_traits::to_entity(entt));
- const auto page = pos / entity_traits::page_size;
- return (page < sparse.size() && sparse[page]) ? (sparse[page] + fast_mod(pos, entity_traits::page_size)) : nullptr;
- }
- [[nodiscard]] auto &sparse_ref(const Entity entt) const {
- ENTT_ASSERT(sparse_ptr(entt), "Invalid element");
- const auto pos = static_cast<size_type>(entity_traits::to_entity(entt));
- return sparse[pos / entity_traits::page_size][fast_mod(pos, entity_traits::page_size)];
- }
- [[nodiscard]] auto &assure_at_least(const Entity entt) {
- const auto pos = static_cast<size_type>(entity_traits::to_entity(entt));
- const auto page = pos / entity_traits::page_size;
- if(!(page < sparse.size())) {
- sparse.resize(page + 1u, nullptr);
- }
- if(!sparse[page]) {
- auto page_allocator{packed.get_allocator()};
- sparse[page] = alloc_traits::allocate(page_allocator, entity_traits::page_size);
- std::uninitialized_fill(sparse[page], sparse[page] + entity_traits::page_size, null);
- }
- auto &elem = sparse[page][fast_mod(pos, entity_traits::page_size)];
- ENTT_ASSERT(entity_traits::to_version(elem) == entity_traits::to_version(tombstone), "Slot not available");
- return elem;
- }
- void release_sparse_pages() {
- auto page_allocator{packed.get_allocator()};
- for(auto &&page: sparse) {
- if(page != nullptr) {
- std::destroy(page, page + entity_traits::page_size);
- alloc_traits::deallocate(page_allocator, page, entity_traits::page_size);
- page = nullptr;
- }
- }
- }
- private:
- virtual const void *get_at(const std::size_t) const {
- return nullptr;
- }
- virtual void swap_at(const std::size_t, const std::size_t) {}
- virtual void move_element(const std::size_t, const std::size_t) {}
- protected:
- /*! @brief Random access iterator type. */
- using basic_iterator = internal::sparse_set_iterator<packed_container_type>;
- /**
- * @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 swap_and_pop(basic_iterator first, basic_iterator last) {
- for(; first != last; ++first) {
- auto &self = sparse_ref(*first);
- const auto entt = entity_traits::to_entity(self);
- sparse_ref(packed.back()) = entity_traits::combine(entt, entity_traits::to_integral(packed.back()));
- packed[static_cast<size_type>(entt)] = packed.back();
- // unnecessary but it helps to detect nasty bugs
- ENTT_ASSERT((packed.back() = tombstone, true), "");
- // lazy self-assignment guard
- self = null;
- packed.pop_back();
- }
- }
- /**
- * @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 in_place_pop(basic_iterator first, basic_iterator last) {
- for(; first != last; ++first) {
- const auto entt = entity_traits::to_entity(std::exchange(sparse_ref(*first), null));
- packed[static_cast<size_type>(entt)] = std::exchange(free_list, entity_traits::combine(entt, entity_traits::reserved));
- }
- }
- /**
- * @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(!contains(entt), "Set already contains entity");
- if(auto &elem = assure_at_least(entt); free_list == null || force_back) {
- packed.push_back(entt);
- elem = entity_traits::combine(static_cast<typename entity_traits::entity_type>(packed.size() - 1u), entity_traits::to_integral(entt));
- return begin();
- } else {
- const auto pos = static_cast<size_type>(entity_traits::to_entity(free_list));
- elem = entity_traits::combine(entity_traits::to_integral(free_list), entity_traits::to_integral(entt));
- free_list = std::exchange(packed[pos], entt);
- return --(end() - pos);
- }
- }
- public:
- /*! @brief Allocator type. */
- using allocator_type = Allocator;
- /*! @brief Underlying entity identifier. */
- using entity_type = Entity;
- /*! @brief Underlying version type. */
- using version_type = typename entity_traits::version_type;
- /*! @brief Unsigned integer type. */
- using size_type = typename packed_container_type::size_type;
- /*! @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 = reverse_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{type_id<void>(), 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 value 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 &value, deletion_policy pol = deletion_policy::swap_and_pop, const allocator_type &allocator = {})
- : sparse{allocator},
- packed{allocator},
- info{&value},
- free_list{tombstone},
- mode{pol} {}
- /**
- * @brief Move constructor.
- * @param other The instance to move from.
- */
- basic_sparse_set(basic_sparse_set &&other) ENTT_NOEXCEPT
- : sparse{std::move(other.sparse)},
- packed{std::move(other.packed)},
- info{other.info},
- free_list{std::exchange(other.free_list, tombstone)},
- mode{other.mode} {}
- /**
- * @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) ENTT_NOEXCEPT
- : sparse{std::move(other.sparse), allocator},
- packed{std::move(other.packed), allocator},
- info{other.info},
- free_list{std::exchange(other.free_list, tombstone)},
- mode{other.mode} {
- ENTT_ASSERT(alloc_traits::is_always_equal::value || packed.get_allocator() == other.packed.get_allocator(), "Copying a sparse set is not allowed");
- }
- /*! @brief Default destructor. */
- virtual ~basic_sparse_set() {
- release_sparse_pages();
- }
- /**
- * @brief Move assignment operator.
- * @param other The instance to move from.
- * @return This sparse set.
- */
- basic_sparse_set &operator=(basic_sparse_set &&other) ENTT_NOEXCEPT {
- ENTT_ASSERT(alloc_traits::is_always_equal::value || packed.get_allocator() == other.packed.get_allocator(), "Copying a sparse set is not allowed");
- release_sparse_pages();
- sparse = std::move(other.sparse);
- packed = std::move(other.packed);
- info = other.info;
- free_list = std::exchange(other.free_list, tombstone);
- mode = other.mode;
- 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) {
- using std::swap;
- swap(sparse, other.sparse);
- swap(packed, other.packed);
- swap(info, other.info);
- swap(free_list, other.free_list);
- swap(mode, other.mode);
- }
- /**
- * @brief Returns the associated allocator.
- * @return The associated allocator.
- */
- [[nodiscard]] constexpr allocator_type get_allocator() const ENTT_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 ENTT_NOEXCEPT {
- return mode;
- }
- /**
- * @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 ENTT_NOEXCEPT {
- return packed.capacity();
- }
- /*! @brief Requests the removal of unused capacity. */
- virtual void 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 the internal packed 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 Extent of the sparse set.
- */
- [[nodiscard]] size_type extent() const ENTT_NOEXCEPT {
- return sparse.size() * entity_traits::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 ENTT_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 ENTT_NOEXCEPT {
- return packed.empty();
- }
- /**
- * @brief Direct access to the internal packed array.
- * @return A pointer to the internal packed array.
- */
- [[nodiscard]] pointer data() const ENTT_NOEXCEPT {
- return packed.data();
- }
- /**
- * @brief Returns an iterator to the beginning.
- *
- * The returned iterator points to the first entity of the internal packed
- * array. 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]] const_iterator begin() const ENTT_NOEXCEPT {
- const auto pos = static_cast<typename iterator::difference_type>(packed.size());
- return iterator{packed, pos};
- }
- /*! @copydoc begin */
- [[nodiscard]] const_iterator cbegin() const ENTT_NOEXCEPT {
- return begin();
- }
- /**
- * @brief Returns an iterator to the end.
- *
- * The returned iterator points to the element following the last entity in
- * a sparse set. Attempting to dereference the returned iterator results in
- * undefined behavior.
- *
- * @return An iterator to the element following the last entity of a sparse
- * set.
- */
- [[nodiscard]] iterator end() const ENTT_NOEXCEPT {
- return iterator{packed, {}};
- }
- /*! @copydoc end */
- [[nodiscard]] const_iterator cend() const ENTT_NOEXCEPT {
- return end();
- }
- /**
- * @brief Returns a reverse iterator to the beginning.
- *
- * The returned iterator points to the first entity of the reversed internal
- * packed array. 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]] const_reverse_iterator rbegin() const ENTT_NOEXCEPT {
- return std::make_reverse_iterator(end());
- }
- /*! @copydoc rbegin */
- [[nodiscard]] const_reverse_iterator crbegin() const ENTT_NOEXCEPT {
- return rbegin();
- }
- /**
- * @brief Returns a reverse iterator to the end.
- *
- * The returned iterator points to the element following the last entity in
- * the reversed sparse set. Attempting to dereference the returned iterator
- * results in undefined behavior.
- *
- * @return An iterator to the element following the last entity of the
- * reversed sparse set.
- */
- [[nodiscard]] reverse_iterator rend() const ENTT_NOEXCEPT {
- return std::make_reverse_iterator(begin());
- }
- /*! @copydoc rend */
- [[nodiscard]] const_reverse_iterator crend() const ENTT_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]] iterator find(const entity_type entt) const ENTT_NOEXCEPT {
- return contains(entt) ? --(end() - index(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 ENTT_NOEXCEPT {
- const auto elem = sparse_ptr(entt);
- constexpr auto cap = entity_traits::to_entity(null);
- // testing versions permits to avoid accessing the packed array
- return elem && (((~cap & entity_traits::to_integral(entt)) ^ entity_traits::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 ENTT_NOEXCEPT {
- const auto elem = sparse_ptr(entt);
- constexpr auto fallback = entity_traits::to_version(tombstone);
- return elem ? entity_traits::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 ENTT_NOEXCEPT {
- ENTT_ASSERT(contains(entt), "Set does not contain entity");
- return static_cast<size_type>(entity_traits::to_entity(sparse_ref(entt)));
- }
- /**
- * @brief Returns the entity at specified location, with bounds checking.
- * @param pos The position for which to return the entity.
- * @return The entity at specified location if any, a null entity otherwise.
- */
- [[nodiscard]] entity_type at(const size_type pos) const ENTT_NOEXCEPT {
- return pos < packed.size() ? packed[pos] : null;
- }
- /**
- * @brief Returns the entity at specified location, without bounds checking.
- * @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 ENTT_NOEXCEPT {
- ENTT_ASSERT(pos < packed.size(), "Position is 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.
- */
- const void *get(const entity_type entt) const ENTT_NOEXCEPT {
- return get_at(index(entt));
- }
- /*! @copydoc get */
- void *get(const entity_type entt) ENTT_NOEXCEPT {
- return const_cast<void *>(std::as_const(*this).get(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 value Optional opaque value to forward to mixins, if any.
- * @return Iterator pointing to the emplaced element in case of success, the
- * `end()` iterator otherwise.
- */
- iterator emplace(const entity_type entt, const void *value = nullptr) {
- return try_emplace(entt, false, value);
- }
- /**
- * @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.
- */
- void bump(const entity_type entt) {
- auto &entity = sparse_ref(entt);
- entity = entity_traits::combine(entity_traits::to_integral(entity), entity_traits::to_integral(entt));
- packed[static_cast<size_type>(entity_traits::to_entity(entity))] = entt;
- }
- /**
- * @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 insert(It first, It last) {
- for(auto it = first; it != last; ++it) {
- try_emplace(*it, true);
- }
- return first == last ? end() : find(*first);
- }
- /**
- * @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 = --(end() - index(entt));
- (mode == deletion_policy::in_place) ? in_place_pop(it, it + 1u) : swap_and_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>) {
- (mode == deletion_policy::in_place) ? in_place_pop(first, last) : swap_and_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{};
- for(; first != last; ++first) {
- count += remove(*first);
- }
- return count;
- }
- /*! @brief Removes all tombstones from the packed array of a sparse set. */
- void compact() {
- size_type from = packed.size();
- for(; from && packed[from - 1u] == tombstone; --from) {}
- for(auto *it = &free_list; *it != null && from; it = std::addressof(packed[entity_traits::to_entity(*it)])) {
- if(const size_type to = entity_traits::to_entity(*it); to < from) {
- --from;
- move_element(from, to);
- using std::swap;
- swap(packed[from], packed[to]);
- const auto entity = static_cast<typename entity_traits::entity_type>(to);
- sparse_ref(packed[to]) = entity_traits::combine(entity, entity_traits::to_integral(packed[to]));
- *it = entity_traits::combine(static_cast<typename entity_traits::entity_type>(from), entity_traits::reserved);
- for(; from && packed[from - 1u] == tombstone; --from) {}
- }
- }
- free_list = tombstone;
- packed.resize(from);
- }
- /**
- * @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) {
- ENTT_ASSERT(contains(lhs) && contains(rhs), "Set does not contain entities");
- auto &entt = sparse_ref(lhs);
- auto &other = sparse_ref(rhs);
- const auto from = entity_traits::to_entity(entt);
- const auto to = entity_traits::to_entity(other);
- // basic no-leak guarantee (with invalid state) if swapping throws
- swap_at(static_cast<size_type>(from), static_cast<size_type>(to));
- entt = entity_traits::combine(to, entity_traits::to_integral(packed[from]));
- other = entity_traits::combine(from, entity_traits::to_integral(packed[to]));
- using std::swap;
- swap(packed[from], packed[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(!(length > packed.size()), "Length exceeds the number of elements");
- ENTT_ASSERT(free_list == null, "Partial sorting with tombstones is not supported");
- algo(packed.rend() - 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_at(next, idx);
- const auto entity = static_cast<typename entity_traits::entity_type>(curr);
- sparse_ref(entt) = entity_traits::combine(entity, entity_traits::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) {
- compact();
- sort_n(packed.size(), std::move(compare), std::move(algo), std::forward<Args>(args)...);
- }
- /**
- * @brief Sort entities according to their order in another sparse set.
- *
- * Entities that are part of both the sparse sets are ordered internally
- * according to the order they have in `other`. All the other entities goes
- * to the end of the list and there are no guarantees on their order.<br/>
- * In other terms, this function can be used to impose the same order on two
- * sets by using one of them as a master and the other one as a slave.
- *
- * Iterating the sparse set with a couple of iterators returns elements in
- * the expected order after a call to `respect`. See `begin` and `end` for
- * more details.
- *
- * @param other The sparse sets that imposes the order of the entities.
- */
- void respect(const basic_sparse_set &other) {
- compact();
- const auto to = other.end();
- auto from = other.begin();
- for(size_type pos = packed.size() - 1; pos && from != to; ++from) {
- if(contains(*from)) {
- if(*from != packed[pos]) {
- // basic no-leak guarantee (with invalid state) if swapping throws
- swap_elements(packed[pos], *from);
- }
- --pos;
- }
- }
- }
- /*! @brief Clears a sparse set. */
- void clear() {
- if(const auto last = end(); free_list == null) {
- in_place_pop(begin(), last);
- } else {
- for(auto &&entity: *this) {
- // tombstone filter on itself
- if(const auto it = find(entity); it != last) {
- in_place_pop(it, it + 1u);
- }
- }
- }
- free_list = tombstone;
- packed.clear();
- }
- /**
- * @brief Returned value type, if any.
- * @return Returned value type, if any.
- */
- const type_info &type() const ENTT_NOEXCEPT {
- return *info;
- }
- /*! @brief Forwards variables to mixins, if any. */
- virtual void bind(any) ENTT_NOEXCEPT {}
- private:
- sparse_container_type sparse;
- packed_container_type packed;
- const type_info *info;
- entity_type free_list;
- deletion_policy mode;
- };
- } // 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/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 "../config/config.h"
- // #include "type_traits.hpp"
- namespace entt {
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- namespace internal {
- template<typename Type, std::size_t, typename = void>
- struct compressed_pair_element {
- using reference = Type &;
- using const_reference = const Type &;
- template<bool Dummy = true, typename = std::enable_if_t<Dummy && std::is_default_constructible_v<Type>>>
- compressed_pair_element()
- : value{} {}
- template<typename Args, typename = std::enable_if_t<!std::is_same_v<std::remove_cv_t<std::remove_reference_t<Args>>, compressed_pair_element>>>
- compressed_pair_element(Args &&args)
- : value{std::forward<Args>(args)} {}
- template<typename... Args, std::size_t... Index>
- compressed_pair_element(std::tuple<Args...> args, std::index_sequence<Index...>)
- : value{std::forward<Args>(std::get<Index>(args))...} {}
- [[nodiscard]] reference get() ENTT_NOEXCEPT {
- return value;
- }
- [[nodiscard]] const_reference get() const ENTT_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<bool Dummy = true, typename = std::enable_if_t<Dummy && std::is_default_constructible_v<base_type>>>
- compressed_pair_element()
- : base_type{} {}
- template<typename Args, typename = std::enable_if_t<!std::is_same_v<std::remove_cv_t<std::remove_reference_t<Args>>, compressed_pair_element>>>
- compressed_pair_element(Args &&args)
- : base_type{std::forward<Args>(args)} {}
- template<typename... Args, std::size_t... Index>
- compressed_pair_element(std::tuple<Args...> args, std::index_sequence<Index...>)
- : base_type{std::forward<Args>(std::get<Index>(args))...} {}
- [[nodiscard]] reference get() ENTT_NOEXCEPT {
- return *this;
- }
- [[nodiscard]] const_reference get() const ENTT_NOEXCEPT {
- return *this;
- }
- };
- } // namespace internal
- /**
- * Internal details not to be documented.
- * @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()
- : 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) = 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)
- : 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)
- : first_base{std::move(args), std::index_sequence_for<Args...>{}},
- second_base{std::move(other), std::index_sequence_for<Other...>{}} {}
- /**
- * @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) = default;
- /**
- * @brief Returns the first element that a pair stores.
- * @return The first element that a pair stores.
- */
- [[nodiscard]] first_type &first() ENTT_NOEXCEPT {
- return static_cast<first_base &>(*this).get();
- }
- /*! @copydoc first */
- [[nodiscard]] const first_type &first() const ENTT_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]] second_type &second() ENTT_NOEXCEPT {
- return static_cast<second_base &>(*this).get();
- }
- /*! @copydoc second */
- [[nodiscard]] const second_type &second() const ENTT_NOEXCEPT {
- return static_cast<const second_base &>(*this).get();
- }
- /**
- * @brief Swaps two compressed pair objects.
- * @param other The compressed pair to swap with.
- */
- void swap(compressed_pair &other) {
- 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>
- decltype(auto) get() ENTT_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>
- decltype(auto) get() const ENTT_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>
- inline void swap(compressed_pair<First, Second> &lhs, compressed_pair<First, Second> &rhs) {
- lhs.swap(rhs);
- }
- } // namespace entt
- // disable structured binding support for clang 6, it messes when specializing tuple_size
- #if !defined __clang_major__ || __clang_major__ > 6
- 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
- #endif
- // #include "../core/iterator.hpp"
- // #include "../core/memory.hpp"
- // #include "../core/type_info.hpp"
- // #include "component.hpp"
- // #include "entity.hpp"
- // #include "fwd.hpp"
- // #include "sigh_storage_mixin.hpp"
- #ifndef ENTT_ENTITY_SIGH_STORAGE_MIXIN_HPP
- #define ENTT_ENTITY_SIGH_STORAGE_MIXIN_HPP
- #include <utility>
- // #include "../config/config.h"
- // #include "../core/any.hpp"
- // #include "../signal/sigh.hpp"
- #ifndef ENTT_SIGNAL_SIGH_HPP
- #define ENTT_SIGNAL_SIGH_HPP
- #include <algorithm>
- #include <functional>
- #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
- #define ENTT_STR(arg) #arg
- #define ENTT_XSTR(arg) ENTT_STR(arg)
- #endif
- #define ENTT_VERSION_MAJOR 3
- #define ENTT_VERSION_MINOR 10
- #define ENTT_VERSION_PATCH 3
- #define ENTT_VERSION \
- ENTT_XSTR(ENTT_VERSION_MAJOR) \
- "." ENTT_XSTR(ENTT_VERSION_MINOR) "." ENTT_XSTR(ENTT_VERSION_PATCH)
- #endif
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #ifndef ENTT_NOEXCEPT
- # define ENTT_NOEXCEPT noexcept
- # define ENTT_NOEXCEPT_IF(expr) noexcept(expr)
- # else
- # define ENTT_NOEXCEPT_IF(...)
- #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
- #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(...) (void(0))
- #elif !defined ENTT_ASSERT
- # include <cassert>
- # define ENTT_ASSERT(condition, ...) assert(condition)
- #endif
- #ifdef ENTT_NO_ETO
- # define ENTT_IGNORE_IF_EMPTY false
- #else
- # define ENTT_IGNORE_IF_EMPTY true
- #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
- #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
- #endif
- // #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"
- #ifndef ENTT_CORE_TYPE_TRAITS_HPP
- #define ENTT_CORE_TYPE_TRAITS_HPP
- #include <cstddef>
- #include <iterator>
- #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
- #define ENTT_STR(arg) #arg
- #define ENTT_XSTR(arg) ENTT_STR(arg)
- #endif
- #define ENTT_VERSION_MAJOR 3
- #define ENTT_VERSION_MINOR 10
- #define ENTT_VERSION_PATCH 3
- #define ENTT_VERSION \
- ENTT_XSTR(ENTT_VERSION_MAJOR) \
- "." ENTT_XSTR(ENTT_VERSION_MINOR) "." ENTT_XSTR(ENTT_VERSION_PATCH)
- #endif
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #ifndef ENTT_NOEXCEPT
- # define ENTT_NOEXCEPT noexcept
- # define ENTT_NOEXCEPT_IF(expr) noexcept(expr)
- # else
- # define ENTT_NOEXCEPT_IF(...)
- #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
- #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(...) (void(0))
- #elif !defined ENTT_ASSERT
- # include <cassert>
- # define ENTT_ASSERT(condition, ...) assert(condition)
- #endif
- #ifdef ENTT_NO_ETO
- # define ENTT_IGNORE_IF_EMPTY false
- #else
- # define ENTT_IGNORE_IF_EMPTY true
- #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
- #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
- #endif
- // #include "fwd.hpp"
- #ifndef ENTT_CORE_FWD_HPP
- #define ENTT_CORE_FWD_HPP
- #include <cstdint>
- #include <type_traits>
- // #include "../config/config.h"
- namespace entt {
- template<std::size_t Len = sizeof(double[2]), std::size_t = alignof(typename std::aligned_storage_t<Len + !Len>)>
- 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<>;
- } // 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.
- * @tparam The size of the type if `sizeof` accepts it, 0 otherwise.
- */
- 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))>>
- : 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 Type First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<std::size_t Index, typename Type, typename... Other>
- struct type_list_element<Index, type_list<Type, Other...>>
- : type_list_element<Index - 1u, type_list<Other...>> {};
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam Type First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<typename Type, typename... Other>
- struct type_list_element<0u, type_list<Type, Other...>> {
- /*! @brief Searched type. */
- using type = Type;
- };
- /**
- * @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 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;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename>
- struct type_list_unique;
- /**
- * @brief Removes duplicates types from a type list.
- * @tparam Type One of the types provided by the given type list.
- * @tparam Other The other types provided by the given type list.
- */
- template<typename Type, typename... Other>
- struct type_list_unique<type_list<Type, Other...>> {
- /*! @brief A type list without duplicate types. */
- using type = std::conditional_t<
- (std::is_same_v<Type, Other> || ...),
- typename type_list_unique<type_list<Other...>>::type,
- type_list_cat_t<type_list<Type>, typename type_list_unique<type_list<Other...>>::type>>;
- };
- /*! @brief Removes duplicates types from a type list. */
- template<>
- struct type_list_unique<type_list<>> {
- /*! @brief A type list without duplicate types. */
- using type = type_list<>;
- };
- /**
- * @brief Helper type.
- * @tparam Type A type list.
- */
- template<typename Type>
- using type_list_unique_t = typename type_list_unique<Type>::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::disjunction<std::is_same<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 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 value. */
- static constexpr auto value = Value;
- };
- /**
- * @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 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 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
- * Internal details not to be documented.
- */
- 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
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /*! @copydoc is_iterator */
- template<typename Type>
- struct is_iterator<Type, std::enable_if_t<!std::is_same_v<std::remove_const_t<std::remove_pointer_t<Type>>, void>>>
- : 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::conjunction<std::is_empty<Type>, std::negation<std::is_final<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;
- /**
- * @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, typename = void>
- struct is_equality_comparable: std::false_type {};
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- 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 Type, std::size_t... Index>
- [[nodiscard]] constexpr bool unpack_maybe_equality_comparable(std::index_sequence<Index...>) {
- return (is_equality_comparable<std::tuple_element_t<Index, Type>>::value && ...);
- }
- template<typename>
- [[nodiscard]] constexpr bool maybe_equality_comparable(choice_t<0>) {
- return true;
- }
- template<typename Type>
- [[nodiscard]] constexpr auto maybe_equality_comparable(choice_t<1>) -> decltype(std::declval<typename Type::value_type>(), bool{}) {
- if constexpr(is_iterator_v<Type>) {
- return true;
- } else if constexpr(std::is_same_v<typename Type::value_type, Type>) {
- return maybe_equality_comparable<Type>(choice<0>);
- } else {
- return is_equality_comparable<typename Type::value_type>::value;
- }
- }
- template<typename Type>
- [[nodiscard]] constexpr std::enable_if_t<is_complete_v<std::tuple_size<std::remove_const_t<Type>>>, bool> maybe_equality_comparable(choice_t<2>) {
- if constexpr(has_tuple_size_value<Type>::value) {
- return unpack_maybe_equality_comparable<Type>(std::make_index_sequence<std::tuple_size<Type>::value>{});
- } else {
- return maybe_equality_comparable<Type>(choice<1>);
- }
- }
- } // namespace internal
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /*! @copydoc is_equality_comparable */
- template<typename Type>
- struct is_equality_comparable<Type, std::void_t<decltype(std::declval<Type>() == std::declval<Type>())>>
- : std::bool_constant<internal::maybe_equality_comparable<Type>(choice<2>)> {};
- /**
- * @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 = std::add_const_t<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;
- } // namespace entt
- #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<char>>
- class basic_dispatcher;
- template<typename>
- class emitter;
- class connection;
- struct scoped_connection;
- template<typename>
- class sink;
- template<typename Type, typename = std::allocator<Type *>>
- class sigh;
- /*! @brief Alias declaration for the most common use case. */
- using dispatcher = basic_dispatcher<>;
- } // namespace entt
- #endif
- namespace entt {
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- namespace internal {
- template<typename Ret, typename... Args>
- auto function_pointer(Ret (*)(Args...)) -> Ret (*)(Args...);
- template<typename Ret, typename Type, typename... Args, typename Other>
- auto function_pointer(Ret (*)(Type, Args...), Other &&) -> Ret (*)(Args...);
- template<typename Class, typename Ret, typename... Args, typename... Other>
- auto function_pointer(Ret (Class::*)(Args...), Other &&...) -> Ret (*)(Args...);
- template<typename Class, typename Ret, typename... Args, typename... Other>
- auto function_pointer(Ret (Class::*)(Args...) const, Other &&...) -> Ret (*)(Args...);
- template<typename Class, typename Type, typename... Other>
- auto function_pointer(Type Class::*, Other &&...) -> Type (*)();
- template<typename... Type>
- using function_pointer_t = decltype(internal::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
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /*! @brief Used to wrap a function or a member of a specified type. */
- template<auto>
- struct connect_arg_t {};
- /*! @brief Constant of type connect_arg_t used to disambiguate calls. */
- template<auto Func>
- inline constexpr connect_arg_t<Func> connect_arg{};
- /**
- * @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...)> {
- template<auto Candidate, std::size_t... Index>
- [[nodiscard]] auto wrap(std::index_sequence<Index...>) ENTT_NOEXCEPT {
- return [](const void *, Args... args) -> Ret {
- [[maybe_unused]] const auto arguments = std::forward_as_tuple(std::forward<Args>(args)...);
- return static_cast<Ret>(std::invoke(Candidate, std::forward<type_list_element_t<Index, type_list<Args...>>>(std::get<Index>(arguments))...));
- };
- }
- template<auto Candidate, typename Type, std::size_t... Index>
- [[nodiscard]] auto wrap(Type &, std::index_sequence<Index...>) ENTT_NOEXCEPT {
- return [](const void *payload, Args... args) -> Ret {
- [[maybe_unused]] const auto arguments = std::forward_as_tuple(std::forward<Args>(args)...);
- Type *curr = static_cast<Type *>(const_cast<constness_as_t<void, Type> *>(payload));
- return static_cast<Ret>(std::invoke(Candidate, *curr, std::forward<type_list_element_t<Index, type_list<Args...>>>(std::get<Index>(arguments))...));
- };
- }
- template<auto Candidate, typename Type, std::size_t... Index>
- [[nodiscard]] auto wrap(Type *, std::index_sequence<Index...>) ENTT_NOEXCEPT {
- return [](const void *payload, Args... args) -> Ret {
- [[maybe_unused]] const auto arguments = std::forward_as_tuple(std::forward<Args>(args)...);
- Type *curr = static_cast<Type *>(const_cast<constness_as_t<void, Type> *>(payload));
- return static_cast<Ret>(std::invoke(Candidate, curr, std::forward<type_list_element_t<Index, type_list<Args...>>>(std::get<Index>(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() ENTT_NOEXCEPT
- : instance{nullptr},
- fn{nullptr} {}
- /**
- * @brief Constructs a delegate and connects a free function or an unbound
- * member.
- * @tparam Candidate Function or member to connect to the delegate.
- */
- template<auto Candidate>
- delegate(connect_arg_t<Candidate>) ENTT_NOEXCEPT {
- connect<Candidate>();
- }
- /**
- * @brief Constructs a delegate and connects a free function with payload or
- * a bound member.
- * @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 object that fits the purpose.
- */
- template<auto Candidate, typename Type>
- delegate(connect_arg_t<Candidate>, Type &&value_or_instance) ENTT_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) ENTT_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() ENTT_NOEXCEPT {
- instance = nullptr;
- if constexpr(std::is_invocable_r_v<Ret, decltype(Candidate), Args...>) {
- fn = [](const void *, Args... args) -> Ret {
- 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) ENTT_NOEXCEPT {
- instance = &value_or_instance;
- if constexpr(std::is_invocable_r_v<Ret, decltype(Candidate), Type &, Args...>) {
- fn = [](const void *payload, Args... args) -> Ret {
- 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) ENTT_NOEXCEPT {
- instance = value_or_instance;
- if constexpr(std::is_invocable_r_v<Ret, decltype(Candidate), Type *, Args...>) {
- fn = [](const void *payload, Args... args) -> Ret {
- 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) ENTT_NOEXCEPT {
- instance = payload;
- fn = function;
- }
- /**
- * @brief Resets a delegate.
- *
- * After a reset, a delegate cannot be invoked anymore.
- */
- void reset() ENTT_NOEXCEPT {
- instance = nullptr;
- fn = nullptr;
- }
- /**
- * @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 ENTT_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 ENTT_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 ENTT_NOEXCEPT {
- return fn == other.fn && instance == other.instance;
- }
- private:
- const void *instance;
- function_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) ENTT_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> {
- /*! @brief A sink is allowed to modify a signal. */
- friend class sink<sigh<Ret(Args...), Allocator>>;
- using alloc_traits = std::allocator_traits<Allocator>;
- static_assert(std::is_same_v<typename alloc_traits::value_type, Ret (*)(Args...)>, "Invalid value type");
- using container_type = std::vector<delegate<Ret(Args...)>, typename alloc_traits::template rebind_alloc<delegate<Ret(Args...)>>>;
- 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()
- : sigh{allocator_type{}} {}
- /**
- * @brief Constructs a signal handler with a given allocator.
- * @param allocator The allocator to use.
- */
- explicit sigh(const allocator_type &allocator)
- : 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) ENTT_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) ENTT_NOEXCEPT
- : calls{std::move(other.calls), allocator} {}
- /**
- * @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) ENTT_NOEXCEPT {
- calls = std::move(other.calls);
- 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) {
- using std::swap;
- swap(calls, other.calls);
- }
- /**
- * @brief Returns the associated allocator.
- * @return The associated allocator.
- */
- [[nodiscard]] constexpr allocator_type get_allocator() const ENTT_NOEXCEPT {
- return calls.get_allocator();
- }
- /**
- * @brief Instance type when it comes to connecting member functions.
- * @tparam Class Type of class to which the member function belongs.
- */
- template<typename Class>
- using instance_type = Class *;
- /**
- * @brief Number of listeners connected to the signal.
- * @return Number of listeners currently connected.
- */
- [[nodiscard]] size_type size() const ENTT_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 ENTT_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 &&call: std::as_const(calls)) {
- call(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 &&call: calls) {
- if constexpr(std::is_void_v<Ret>) {
- if constexpr(std::is_invocable_r_v<bool, Func>) {
- call(args...);
- if(func()) { break; }
- } else {
- call(args...);
- func();
- }
- } else {
- if constexpr(std::is_invocable_r_v<bool, Func, Ret>) {
- if(func(call(args...))) { break; }
- } else {
- func(call(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 {
- /*! @brief A sink is allowed to create connection objects. */
- template<typename>
- friend class sink;
- connection(delegate<void(void *)> fn, void *ref)
- : disconnect{fn}, signal{ref} {}
- public:
- /*! @brief Default constructor. */
- connection() = default;
- /**
- * @brief Checks whether a connection is properly initialized.
- * @return True if the connection is properly initialized, false otherwise.
- */
- [[nodiscard]] explicit operator bool() const ENTT_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) ENTT_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) ENTT_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 = std::move(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 ENTT_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 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>();
- }
- public:
- /**
- * @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) ENTT_NOEXCEPT
- : offset{},
- 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 ENTT_NOEXCEPT {
- return signal->calls.empty();
- }
- /**
- * @brief Returns a sink that connects before a given free function or an
- * unbound member.
- * @tparam Function A valid free function pointer.
- * @return A properly initialized sink object.
- */
- template<auto Function>
- [[nodiscard]] sink before() {
- delegate<Ret(Args...)> call{};
- call.template connect<Function>();
- const auto &calls = signal->calls;
- const auto it = std::find(calls.cbegin(), calls.cend(), std::move(call));
- sink other{*this};
- other.offset = calls.cend() - it;
- return other;
- }
- /**
- * @brief Returns a sink that connects before a free function with payload
- * or a bound member.
- * @tparam Candidate Member or free function to look for.
- * @tparam Type Type of class or type of payload.
- * @param value_or_instance A valid object that fits the purpose.
- * @return A properly initialized sink object.
- */
- template<auto Candidate, typename Type>
- [[nodiscard]] sink before(Type &&value_or_instance) {
- delegate<Ret(Args...)> call{};
- call.template connect<Candidate>(value_or_instance);
- const auto &calls = signal->calls;
- const auto it = std::find(calls.cbegin(), calls.cend(), std::move(call));
- sink other{*this};
- other.offset = calls.cend() - it;
- return other;
- }
- /**
- * @brief Returns a sink that connects before a given instance or specific
- * payload.
- * @tparam Type Type of class or type of payload.
- * @param value_or_instance A valid object that fits the purpose.
- * @return A properly initialized sink object.
- */
- template<typename Type>
- [[nodiscard]] sink before(Type &value_or_instance) {
- return before(&value_or_instance);
- }
- /**
- * @brief Returns a sink that connects before a given instance or specific
- * payload.
- * @tparam Type Type of class or type of payload.
- * @param value_or_instance A valid pointer that fits the purpose.
- * @return A properly initialized sink object.
- */
- template<typename Type>
- [[nodiscard]] sink before(Type *value_or_instance) {
- sink other{*this};
- if(value_or_instance) {
- const auto &calls = signal->calls;
- const auto it = std::find_if(calls.cbegin(), calls.cend(), [value_or_instance](const auto &delegate) {
- return delegate.data() == value_or_instance;
- });
- other.offset = calls.cend() - it;
- }
- return other;
- }
- /**
- * @brief Returns a sink that connects before anything else.
- * @return A properly initialized sink object.
- */
- [[nodiscard]] sink before() {
- sink other{*this};
- other.offset = signal->calls.size();
- return other;
- }
- /**
- * @brief Connects a free function or an unbound member to a signal.
- *
- * The signal handler performs checks to avoid multiple connections for the
- * same function.
- *
- * @tparam Candidate Function or member to connect to the signal.
- * @return A properly initialized connection object.
- */
- template<auto Candidate>
- connection connect() {
- disconnect<Candidate>();
- delegate<Ret(Args...)> call{};
- call.template connect<Candidate>();
- signal->calls.insert(signal->calls.end() - offset, std::move(call));
- delegate<void(void *)> conn{};
- conn.template connect<&release<Candidate>>();
- return {std::move(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. On the other side, the signal handler performs
- * checks to avoid multiple connections for the same function.<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 object 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<Ret(Args...)> call{};
- call.template connect<Candidate>(value_or_instance);
- signal->calls.insert(signal->calls.end() - offset, std::move(call));
- delegate<void(void *)> conn{};
- conn.template connect<&release<Candidate, Type>>(value_or_instance);
- return {std::move(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() {
- auto &calls = signal->calls;
- delegate<Ret(Args...)> call{};
- call.template connect<Candidate>();
- calls.erase(std::remove(calls.begin(), calls.end(), std::move(call)), calls.end());
- }
- /**
- * @brief Disconnects a free function with payload or a bound member from a
- * signal.
- * @tparam Candidate Function or member to disconnect from the signal.
- * @tparam Type Type of class or type of payload.
- * @param value_or_instance A valid object that fits the purpose.
- */
- template<auto Candidate, typename Type>
- void disconnect(Type &&value_or_instance) {
- auto &calls = signal->calls;
- delegate<Ret(Args...)> call{};
- call.template connect<Candidate>(value_or_instance);
- calls.erase(std::remove(calls.begin(), calls.end(), std::move(call)), calls.end());
- }
- /**
- * @brief Disconnects free functions with payload or bound members from a
- * signal.
- * @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 Disconnects free functions with payload or bound members from a
- * signal.
- * @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) {
- if(value_or_instance) {
- auto &calls = signal->calls;
- auto predicate = [value_or_instance](const auto &delegate) { return delegate.data() == value_or_instance; };
- calls.erase(std::remove_if(calls.begin(), calls.end(), std::move(predicate)), calls.end());
- }
- }
- /*! @brief Disconnects all the listeners from a signal. */
- void disconnect() {
- signal->calls.clear();
- }
- private:
- difference_type offset;
- 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 "fwd.hpp"
- namespace entt {
- /**
- * @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 The type of the underlying storage.
- */
- template<typename Type>
- class sigh_storage_mixin final: public Type {
- using basic_iterator = typename Type::basic_iterator;
- template<typename Func>
- void notify_destruction(basic_iterator first, basic_iterator last, Func func) {
- ENTT_ASSERT(owner != nullptr, "Invalid pointer to registry");
- for(; first != last; ++first) {
- const auto entt = *first;
- destruction.publish(*owner, entt);
- const auto it = Type::find(entt);
- func(it, it + 1u);
- }
- }
- void swap_and_pop(basic_iterator first, basic_iterator last) final {
- notify_destruction(std::move(first), std::move(last), [this](auto... args) { Type::swap_and_pop(args...); });
- }
- void in_place_pop(basic_iterator first, basic_iterator last) final {
- notify_destruction(std::move(first), std::move(last), [this](auto... args) { Type::in_place_pop(args...); });
- }
- basic_iterator try_emplace(const typename Type::entity_type entt, const bool force_back, const void *value) final {
- ENTT_ASSERT(owner != nullptr, "Invalid pointer to registry");
- Type::try_emplace(entt, force_back, value);
- construction.publish(*owner, entt);
- return Type::find(entt);
- }
- public:
- /*! @brief Underlying entity identifier. */
- using entity_type = typename Type::entity_type;
- /*! @brief Inherited constructors. */
- using Type::Type;
- /**
- * @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() ENTT_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() ENTT_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() ENTT_NOEXCEPT {
- return sink{destruction};
- }
- /**
- * @brief Assigns entities to a storage.
- * @tparam Args Types of arguments to use to construct the object.
- * @param entt A valid identifier.
- * @param args Parameters to use to initialize the object.
- * @return A reference to the newly created object.
- */
- template<typename... Args>
- decltype(auto) emplace(const entity_type entt, Args &&...args) {
- ENTT_ASSERT(owner != nullptr, "Invalid pointer to registry");
- Type::emplace(entt, std::forward<Args>(args)...);
- construction.publish(*owner, entt);
- return this->get(entt);
- }
- /**
- * @brief Patches the given instance for an entity.
- * @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) {
- ENTT_ASSERT(owner != nullptr, "Invalid pointer to registry");
- Type::patch(entt, std::forward<Func>(func)...);
- update.publish(*owner, entt);
- return this->get(entt);
- }
- /**
- * @brief Assigns entities to a storage.
- * @tparam It Type of input iterator.
- * @tparam Args Types of arguments to use to construct the objects assigned
- * to the entities.
- * @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 initialize the objects assigned to the
- * entities.
- */
- template<typename It, typename... Args>
- void insert(It first, It last, Args &&...args) {
- ENTT_ASSERT(owner != nullptr, "Invalid pointer to registry");
- Type::insert(first, last, std::forward<Args>(args)...);
- for(auto it = construction.empty() ? last : first; it != last; ++it) {
- construction.publish(*owner, *it);
- }
- }
- /**
- * @brief Forwards variables to mixins, if any.
- * @param value A variable wrapped in an opaque container.
- */
- void bind(any value) ENTT_NOEXCEPT final {
- auto *reg = any_cast<basic_registry<entity_type>>(&value);
- owner = reg ? reg : owner;
- Type::bind(std::move(value));
- }
- private:
- sigh<void(basic_registry<entity_type> &, const entity_type)> construction{};
- sigh<void(basic_registry<entity_type> &, const entity_type)> destruction{};
- sigh<void(basic_registry<entity_type> &, const entity_type)> update{};
- basic_registry<entity_type> *owner{};
- };
- } // namespace entt
- #endif
- // #include "sparse_set.hpp"
- namespace entt {
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- namespace internal {
- template<typename Container>
- class storage_iterator final {
- friend storage_iterator<const Container>;
- using container_type = std::remove_const_t<Container>;
- using alloc_traits = std::allocator_traits<typename container_type::allocator_type>;
- using comp_traits = component_traits<typename container_type::value_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;
- storage_iterator() ENTT_NOEXCEPT = default;
- storage_iterator(Container *ref, difference_type idx) ENTT_NOEXCEPT
- : packed{ref},
- offset{idx} {}
- template<bool Const = std::is_const_v<Container>, typename = std::enable_if_t<Const>>
- storage_iterator(const storage_iterator<std::remove_const_t<Container>> &other) ENTT_NOEXCEPT
- : packed{other.packed},
- offset{other.offset} {}
- storage_iterator &operator++() ENTT_NOEXCEPT {
- return --offset, *this;
- }
- storage_iterator operator++(int) ENTT_NOEXCEPT {
- storage_iterator orig = *this;
- return ++(*this), orig;
- }
- storage_iterator &operator--() ENTT_NOEXCEPT {
- return ++offset, *this;
- }
- storage_iterator operator--(int) ENTT_NOEXCEPT {
- storage_iterator orig = *this;
- return operator--(), orig;
- }
- storage_iterator &operator+=(const difference_type value) ENTT_NOEXCEPT {
- offset -= value;
- return *this;
- }
- storage_iterator operator+(const difference_type value) const ENTT_NOEXCEPT {
- storage_iterator copy = *this;
- return (copy += value);
- }
- storage_iterator &operator-=(const difference_type value) ENTT_NOEXCEPT {
- return (*this += -value);
- }
- storage_iterator operator-(const difference_type value) const ENTT_NOEXCEPT {
- return (*this + -value);
- }
- [[nodiscard]] reference operator[](const difference_type value) const ENTT_NOEXCEPT {
- const auto pos = index() - value;
- return (*packed)[pos / comp_traits::page_size][fast_mod(pos, comp_traits::page_size)];
- }
- [[nodiscard]] pointer operator->() const ENTT_NOEXCEPT {
- const auto pos = index();
- return (*packed)[pos / comp_traits::page_size] + fast_mod(pos, comp_traits::page_size);
- }
- [[nodiscard]] reference operator*() const ENTT_NOEXCEPT {
- return *operator->();
- }
- [[nodiscard]] difference_type index() const ENTT_NOEXCEPT {
- return offset - 1;
- }
- private:
- Container *packed;
- difference_type offset;
- };
- template<typename CLhs, typename CRhs>
- [[nodiscard]] std::ptrdiff_t operator-(const storage_iterator<CLhs> &lhs, const storage_iterator<CRhs> &rhs) ENTT_NOEXCEPT {
- return rhs.index() - lhs.index();
- }
- template<typename CLhs, typename CRhs>
- [[nodiscard]] bool operator==(const storage_iterator<CLhs> &lhs, const storage_iterator<CRhs> &rhs) ENTT_NOEXCEPT {
- return lhs.index() == rhs.index();
- }
- template<typename CLhs, typename CRhs>
- [[nodiscard]] bool operator!=(const storage_iterator<CLhs> &lhs, const storage_iterator<CRhs> &rhs) ENTT_NOEXCEPT {
- return !(lhs == rhs);
- }
- template<typename CLhs, typename CRhs>
- [[nodiscard]] bool operator<(const storage_iterator<CLhs> &lhs, const storage_iterator<CRhs> &rhs) ENTT_NOEXCEPT {
- return lhs.index() > rhs.index();
- }
- template<typename CLhs, typename CRhs>
- [[nodiscard]] bool operator>(const storage_iterator<CLhs> &lhs, const storage_iterator<CRhs> &rhs) ENTT_NOEXCEPT {
- return lhs.index() < rhs.index();
- }
- template<typename CLhs, typename CRhs>
- [[nodiscard]] bool operator<=(const storage_iterator<CLhs> &lhs, const storage_iterator<CRhs> &rhs) ENTT_NOEXCEPT {
- return !(lhs > rhs);
- }
- template<typename CLhs, typename CRhs>
- [[nodiscard]] bool operator>=(const storage_iterator<CLhs> &lhs, const storage_iterator<CRhs> &rhs) ENTT_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 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;
- extended_storage_iterator() = default;
- extended_storage_iterator(It 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> && ...)>>
- extended_storage_iterator(const extended_storage_iterator<It, Args...> &other)
- : it{other.it} {}
- extended_storage_iterator &operator++() ENTT_NOEXCEPT {
- return ++std::get<It>(it), (++std::get<Other>(it), ...), *this;
- }
- extended_storage_iterator operator++(int) ENTT_NOEXCEPT {
- extended_storage_iterator orig = *this;
- return ++(*this), orig;
- }
- [[nodiscard]] pointer operator->() const ENTT_NOEXCEPT {
- return operator*();
- }
- [[nodiscard]] reference operator*() const ENTT_NOEXCEPT {
- return {*std::get<It>(it), *std::get<Other>(it)...};
- }
- template<typename... CLhs, typename... CRhs>
- friend bool operator==(const extended_storage_iterator<CLhs...> &, const extended_storage_iterator<CRhs...> &) ENTT_NOEXCEPT;
- private:
- std::tuple<It, Other...> it;
- };
- template<typename... CLhs, typename... CRhs>
- [[nodiscard]] bool operator==(const extended_storage_iterator<CLhs...> &lhs, const extended_storage_iterator<CRhs...> &rhs) ENTT_NOEXCEPT {
- return std::get<0>(lhs.it) == std::get<0>(rhs.it);
- }
- template<typename... CLhs, typename... CRhs>
- [[nodiscard]] bool operator!=(const extended_storage_iterator<CLhs...> &lhs, const extended_storage_iterator<CRhs...> &rhs) ENTT_NOEXCEPT {
- return !(lhs == rhs);
- }
- } // namespace internal
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /**
- * @brief Basic 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 Entity A valid entity type (see entt_traits for more details).
- * @tparam Type Type of objects assigned to the entities.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- */
- template<typename Entity, typename Type, typename Allocator, typename>
- class basic_storage: public basic_sparse_set<Entity, typename std::allocator_traits<Allocator>::template rebind_alloc<Entity>> {
- static_assert(std::is_move_constructible_v<Type> && std::is_move_assignable_v<Type>, "The type must be at least move constructible/assignable");
- using alloc_traits = std::allocator_traits<Allocator>;
- static_assert(std::is_same_v<typename alloc_traits::value_type, Type>, "Invalid value type");
- using underlying_type = basic_sparse_set<Entity, typename alloc_traits::template rebind_alloc<Entity>>;
- using container_type = std::vector<typename alloc_traits::pointer, typename alloc_traits::template rebind_alloc<typename alloc_traits::pointer>>;
- using comp_traits = component_traits<Type>;
- [[nodiscard]] auto &element_at(const std::size_t pos) const {
- return packed.first()[pos / comp_traits::page_size][fast_mod(pos, comp_traits::page_size)];
- }
- auto assure_at_least(const std::size_t pos) {
- auto &&container = packed.first();
- const auto idx = pos / comp_traits::page_size;
- if(!(idx < container.size())) {
- auto curr = container.size();
- container.resize(idx + 1u, nullptr);
- ENTT_TRY {
- for(const auto last = container.size(); curr < last; ++curr) {
- container[curr] = alloc_traits::allocate(packed.second(), comp_traits::page_size);
- }
- }
- ENTT_CATCH {
- container.resize(curr);
- ENTT_THROW;
- }
- }
- return container[idx] + fast_mod(pos, comp_traits::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 = assure_at_least(static_cast<size_type>(it.index()));
- entt::uninitialized_construct_using_allocator(to_address(elem), packed.second(), std::forward<Args>(args)...);
- }
- ENTT_CATCH {
- if constexpr(comp_traits::in_place_delete) {
- base_type::in_place_pop(it, it + 1u);
- } else {
- base_type::swap_and_pop(it, it + 1u);
- }
- ENTT_THROW;
- }
- return it;
- }
- void shrink_to_size(const std::size_t sz) {
- for(auto pos = sz, length = base_type::size(); pos < length; ++pos) {
- if constexpr(comp_traits::in_place_delete) {
- if(base_type::at(pos) != tombstone) {
- std::destroy_at(std::addressof(element_at(pos)));
- }
- } else {
- std::destroy_at(std::addressof(element_at(pos)));
- }
- }
- auto &&container = packed.first();
- auto page_allocator{packed.second()};
- const auto from = (sz + comp_traits::page_size - 1u) / comp_traits::page_size;
- for(auto pos = from, last = container.size(); pos < last; ++pos) {
- alloc_traits::deallocate(page_allocator, container[pos], comp_traits::page_size);
- }
- container.resize(from);
- }
- private:
- const void *get_at(const std::size_t pos) const final {
- return std::addressof(element_at(pos));
- }
- void swap_at(const std::size_t lhs, const std::size_t rhs) final {
- using std::swap;
- swap(element_at(lhs), element_at(rhs));
- }
- void move_element(const std::size_t from, const std::size_t to) final {
- auto &elem = element_at(from);
- entt::uninitialized_construct_using_allocator(to_address(assure_at_least(to)), packed.second(), std::move(elem));
- std::destroy_at(std::addressof(elem));
- }
- protected:
- /**
- * @brief Erases elements from a storage.
- * @param first An iterator to the first element to erase.
- * @param last An iterator past the last element to erase.
- */
- void swap_and_pop(typename underlying_type::basic_iterator first, typename underlying_type::basic_iterator last) override {
- for(; first != last; ++first) {
- // cannot use first::index() because it would break with cross iterators
- const auto pos = base_type::index(*first);
- auto &elem = element_at(base_type::size() - 1u);
- // destroying on exit allows reentrant destructors
- [[maybe_unused]] auto unused = std::exchange(element_at(pos), std::move(elem));
- std::destroy_at(std::addressof(elem));
- base_type::swap_and_pop(first, first + 1u);
- }
- }
- /**
- * @brief Erases elements from a storage.
- * @param first An iterator to the first element to erase.
- * @param last An iterator past the last element to erase.
- */
- void in_place_pop(typename underlying_type::basic_iterator first, typename underlying_type::basic_iterator last) override {
- for(; first != last; ++first) {
- // cannot use first::index() because it would break with cross iterators
- const auto pos = base_type::index(*first);
- base_type::in_place_pop(first, first + 1u);
- std::destroy_at(std::addressof(element_at(pos)));
- }
- }
- /**
- * @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.
- */
- typename underlying_type::basic_iterator try_emplace([[maybe_unused]] const Entity entt, const bool force_back, const void *value) override {
- if(value) {
- if constexpr(std::is_copy_constructible_v<value_type>) {
- return emplace_element(entt, force_back, *static_cast<const value_type *>(value));
- } else {
- return base_type::end();
- }
- } else {
- if constexpr(std::is_default_constructible_v<value_type>) {
- return emplace_element(entt, force_back);
- } else {
- return base_type::end();
- }
- }
- }
- public:
- /*! @brief Base type. */
- using base_type = underlying_type;
- /*! @brief Allocator type. */
- using allocator_type = Allocator;
- /*! @brief Type of the objects assigned to entities. */
- using value_type = Type;
- /*! @brief Underlying entity identifier. */
- using entity_type = Entity;
- /*! @brief Unsigned integer type. */
- using size_type = std::size_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>;
- /*! @brief Constant random access iterator type. */
- using const_iterator = internal::storage_iterator<const container_type>;
- /*! @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 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<value_type>(), deletion_policy{comp_traits::in_place_delete}, allocator},
- packed{container_type{allocator}, allocator} {}
- /**
- * @brief Move constructor.
- * @param other The instance to move from.
- */
- basic_storage(basic_storage &&other) ENTT_NOEXCEPT
- : base_type{std::move(other)},
- packed{std::move(other.packed)} {}
- /**
- * @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) ENTT_NOEXCEPT
- : base_type{std::move(other), allocator},
- packed{container_type{std::move(other.packed.first()), allocator}, allocator} {
- ENTT_ASSERT(alloc_traits::is_always_equal::value || packed.second() == other.packed.second(), "Copying a storage is not allowed");
- }
- /*! @brief Default destructor. */
- ~basic_storage() override {
- shrink_to_size(0u);
- }
- /**
- * @brief Move assignment operator.
- * @param other The instance to move from.
- * @return This storage.
- */
- basic_storage &operator=(basic_storage &&other) ENTT_NOEXCEPT {
- ENTT_ASSERT(alloc_traits::is_always_equal::value || packed.second() == other.packed.second(), "Copying a storage is not allowed");
- shrink_to_size(0u);
- base_type::operator=(std::move(other));
- packed.first() = std::move(other.packed.first());
- propagate_on_container_move_assignment(packed.second(), other.packed.second());
- 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) {
- using std::swap;
- underlying_type::swap(other);
- propagate_on_container_swap(packed.second(), other.packed.second());
- swap(packed.first(), other.packed.first());
- }
- /**
- * @brief Returns the associated allocator.
- * @return The associated allocator.
- */
- [[nodiscard]] constexpr allocator_type get_allocator() const ENTT_NOEXCEPT {
- return allocator_type{packed.second()};
- }
- /**
- * @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 ENTT_NOEXCEPT override {
- return packed.first().size() * comp_traits::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 ENTT_NOEXCEPT {
- return packed.first().data();
- }
- /*! @copydoc raw */
- [[nodiscard]] pointer raw() ENTT_NOEXCEPT {
- return packed.first().data();
- }
- /**
- * @brief Returns an iterator to the beginning.
- *
- * The returned iterator points to the first instance of the internal array.
- * 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 ENTT_NOEXCEPT {
- const auto pos = static_cast<typename iterator::difference_type>(base_type::size());
- return const_iterator{&packed.first(), pos};
- }
- /*! @copydoc cbegin */
- [[nodiscard]] const_iterator begin() const ENTT_NOEXCEPT {
- return cbegin();
- }
- /*! @copydoc begin */
- [[nodiscard]] iterator begin() ENTT_NOEXCEPT {
- const auto pos = static_cast<typename iterator::difference_type>(base_type::size());
- return iterator{&packed.first(), pos};
- }
- /**
- * @brief Returns an iterator to the end.
- *
- * The returned iterator points to the element following the last instance
- * of the internal array. Attempting to dereference the returned iterator
- * results in undefined behavior.
- *
- * @return An iterator to the element following the last instance of the
- * internal array.
- */
- [[nodiscard]] const_iterator cend() const ENTT_NOEXCEPT {
- return const_iterator{&packed.first(), {}};
- }
- /*! @copydoc cend */
- [[nodiscard]] const_iterator end() const ENTT_NOEXCEPT {
- return cend();
- }
- /*! @copydoc end */
- [[nodiscard]] iterator end() ENTT_NOEXCEPT {
- return iterator{&packed.first(), {}};
- }
- /**
- * @brief Returns a reverse iterator to the beginning.
- *
- * The returned iterator points to the first instance of the reversed
- * internal array. 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 ENTT_NOEXCEPT {
- return std::make_reverse_iterator(cend());
- }
- /*! @copydoc crbegin */
- [[nodiscard]] const_reverse_iterator rbegin() const ENTT_NOEXCEPT {
- return crbegin();
- }
- /*! @copydoc rbegin */
- [[nodiscard]] reverse_iterator rbegin() ENTT_NOEXCEPT {
- return std::make_reverse_iterator(end());
- }
- /**
- * @brief Returns a reverse iterator to the end.
- *
- * The returned iterator points to the element following the last instance
- * of the reversed internal array. Attempting to dereference the returned
- * iterator results in undefined behavior.
- *
- * @return An iterator to the element following the last instance of the
- * reversed internal array.
- */
- [[nodiscard]] const_reverse_iterator crend() const ENTT_NOEXCEPT {
- return std::make_reverse_iterator(cbegin());
- }
- /*! @copydoc crend */
- [[nodiscard]] const_reverse_iterator rend() const ENTT_NOEXCEPT {
- return crend();
- }
- /*! @copydoc rend */
- [[nodiscard]] reverse_iterator rend() ENTT_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 ENTT_NOEXCEPT {
- return element_at(base_type::index(entt));
- }
- /*! @copydoc get */
- [[nodiscard]] value_type &get(const entity_type entt) 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 ENTT_NOEXCEPT {
- return std::forward_as_tuple(get(entt));
- }
- /*! @copydoc get_as_tuple */
- [[nodiscard]] std::tuple<value_type &> get_as_tuple(const entity_type entt) 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>) {
- 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.
- */
- template<typename It>
- void insert(It first, It last, const value_type &value = {}) {
- for(; first != last; ++first) {
- emplace_element(*first, true, value);
- }
- }
- /**
- * @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.
- */
- template<typename EIt, typename CIt, typename = std::enable_if_t<std::is_same_v<typename std::iterator_traits<CIt>::value_type, value_type>>>
- void insert(EIt first, EIt last, CIt from) {
- for(; first != last; ++first, ++from) {
- emplace_element(*first, true, *from);
- }
- }
- /**
- * @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 component.
- *
- * @return An iterable object to use to _visit_ the storage.
- */
- [[nodiscard]] iterable each() ENTT_NOEXCEPT {
- return {internal::extended_storage_iterator{base_type::begin(), begin()}, internal::extended_storage_iterator{base_type::end(), end()}};
- }
- /*! @copydoc each */
- [[nodiscard]] const_iterable each() const ENTT_NOEXCEPT {
- return {internal::extended_storage_iterator{base_type::cbegin(), cbegin()}, internal::extended_storage_iterator{base_type::cend(), cend()}};
- }
- private:
- compressed_pair<container_type, allocator_type> packed;
- };
- /*! @copydoc basic_storage */
- template<typename Entity, typename Type, typename Allocator>
- class basic_storage<Entity, Type, Allocator, std::enable_if_t<ignore_as_empty_v<Type>>>
- : 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 underlying_type = basic_sparse_set<Entity, typename alloc_traits::template rebind_alloc<Entity>>;
- using comp_traits = component_traits<Type>;
- public:
- /*! @brief Base type. */
- using base_type = underlying_type;
- /*! @brief Allocator type. */
- using allocator_type = Allocator;
- /*! @brief Type of the objects assigned to entities. */
- using value_type = Type;
- /*! @brief Underlying entity identifier. */
- using entity_type = Entity;
- /*! @brief Unsigned integer type. */
- using size_type = std::size_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 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<value_type>(), deletion_policy{comp_traits::in_place_delete}, allocator} {}
- /**
- * @brief Move constructor.
- * @param other The instance to move from.
- */
- basic_storage(basic_storage &&other) ENTT_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) ENTT_NOEXCEPT
- : base_type{std::move(other), allocator} {}
- /**
- * @brief Move assignment operator.
- * @param other The instance to move from.
- * @return This storage.
- */
- basic_storage &operator=(basic_storage &&other) ENTT_NOEXCEPT = default;
- /**
- * @brief Returns the associated allocator.
- * @return The associated allocator.
- */
- [[nodiscard]] constexpr allocator_type get_allocator() const ENTT_NOEXCEPT {
- 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 ENTT_NOEXCEPT {
- ENTT_ASSERT(base_type::contains(entt), "Storage does not contain entity");
- }
- /**
- * @brief Returns an empty tuple.
- *
- * @warning
- * Attempting to use an entity that doesn't belong to the storage results in
- * undefined behavior.
- *
- * @param entt A valid identifier.
- * @return Returns an empty tuple.
- */
- [[nodiscard]] std::tuple<> get_as_tuple([[maybe_unused]] const entity_type entt) const ENTT_NOEXCEPT {
- ENTT_ASSERT(base_type::contains(entt), "Storage does not contain 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.
- *
- * @tparam Args Types of arguments to use to construct the object.
- * @param entt A valid identifier.
- */
- template<typename... Args>
- void emplace(const entity_type entt, Args &&...) {
- 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), "Storage does not contain entity");
- (std::forward<Func>(func)(), ...);
- }
- /**
- * @brief Assigns entities to a storage.
- * @tparam It Type of input iterator.
- * @tparam Args Types of optional arguments.
- * @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, typename... Args>
- void insert(It first, It last, Args &&...) {
- 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() ENTT_NOEXCEPT {
- return {internal::extended_storage_iterator{base_type::begin()}, internal::extended_storage_iterator{base_type::end()}};
- }
- /*! @copydoc each */
- [[nodiscard]] const_iterable each() const ENTT_NOEXCEPT {
- return {internal::extended_storage_iterator{base_type::cbegin()}, internal::extended_storage_iterator{base_type::cend()}};
- }
- };
- /**
- * @brief Provides a common way to access certain properties of storage types.
- * @tparam Entity A valid entity type (see entt_traits for more details).
- * @tparam Type Type of objects managed by the storage class.
- */
- template<typename Entity, typename Type, typename = void>
- struct storage_traits {
- /*! @brief Resulting type after component-to-storage conversion. */
- using storage_type = sigh_storage_mixin<basic_storage<Entity, Type>>;
- };
- } // namespace entt
- #endif
- // #include "utility.hpp"
- namespace entt {
- /**
- * @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, typename>
- class basic_group;
- /**
- * @brief Non-owning group.
- *
- * A non-owning group returns all entities and only the entities that have at
- * least the given components. Moreover, it's guaranteed that the entity list
- * is tightly packed in memory for fast iterations.
- *
- * @b Important
- *
- * Iterators aren't invalidated if:
- *
- * * New instances of the given components are created and assigned to entities.
- * * The entity currently pointed is modified (as an example, if one of the
- * given components is removed from the entity to which the iterator points).
- * * The entity currently pointed is destroyed.
- *
- * In all other cases, modifying the pools iterated by the group in any way
- * invalidates all the iterators and using them results in undefined behavior.
- *
- * @note
- * Groups share references to the underlying data structures of the registry
- * that generated them. Therefore any change to the entities and to the
- * components made by means of the registry are immediately reflected by all the
- * groups.<br/>
- * Moreover, sorting a non-owning group affects all the instances of the same
- * group (it means that users don't have to call `sort` on each instance to sort
- * all of them because they _share_ entities and components).
- *
- * @warning
- * Lifetime of a group must not overcome that of the registry that generated it.
- * In any other case, attempting to use a group results in undefined behavior.
- *
- * @tparam Entity A valid entity type (see entt_traits for more details).
- * @tparam Get Type of components observed by the group.
- * @tparam Exclude Types of components used to filter the group.
- */
- template<typename Entity, typename... Get, typename... Exclude>
- class basic_group<Entity, owned_t<>, get_t<Get...>, exclude_t<Exclude...>> {
- /*! @brief A registry is allowed to create groups. */
- friend class basic_registry<Entity>;
- template<typename Comp>
- using storage_type = constness_as_t<typename storage_traits<Entity, std::remove_const_t<Comp>>::storage_type, Comp>;
- using basic_common_type = std::common_type_t<typename storage_type<Get>::base_type...>;
- struct extended_group_iterator final {
- using difference_type = std::ptrdiff_t;
- using value_type = decltype(std::tuple_cat(std::tuple<Entity>{}, std::declval<basic_group>().get({})));
- using pointer = input_iterator_pointer<value_type>;
- using reference = value_type;
- using iterator_category = std::input_iterator_tag;
- extended_group_iterator() = default;
- extended_group_iterator(typename basic_common_type::iterator from, const std::tuple<storage_type<Get> *...> &args)
- : it{from},
- pools{args} {}
- extended_group_iterator &operator++() ENTT_NOEXCEPT {
- return ++it, *this;
- }
- extended_group_iterator operator++(int) ENTT_NOEXCEPT {
- extended_group_iterator orig = *this;
- return ++(*this), orig;
- }
- [[nodiscard]] reference operator*() const ENTT_NOEXCEPT {
- const auto entt = *it;
- return std::tuple_cat(std::make_tuple(entt), std::get<storage_type<Get> *>(pools)->get_as_tuple(entt)...);
- }
- [[nodiscard]] pointer operator->() const ENTT_NOEXCEPT {
- return operator*();
- }
- [[nodiscard]] bool operator==(const extended_group_iterator &other) const ENTT_NOEXCEPT {
- return other.it == it;
- }
- [[nodiscard]] bool operator!=(const extended_group_iterator &other) const ENTT_NOEXCEPT {
- return !(*this == other);
- }
- private:
- typename basic_common_type::iterator it;
- std::tuple<storage_type<Get> *...> pools;
- };
- basic_group(basic_common_type &ref, storage_type<Get> &...gpool) ENTT_NOEXCEPT
- : handler{&ref},
- pools{&gpool...} {}
- public:
- /*! @brief Underlying entity identifier. */
- using entity_type = Entity;
- /*! @brief Unsigned integer type. */
- using size_type = std::size_t;
- /*! @brief Common type among all storage types. */
- using base_type = basic_common_type;
- /*! @brief Random access iterator type. */
- using iterator = typename base_type::iterator;
- /*! @brief Reversed iterator type. */
- using reverse_iterator = typename base_type::reverse_iterator;
- /*! @brief Iterable group type. */
- using iterable = iterable_adaptor<extended_group_iterator>;
- /*! @brief Default constructor to use to create empty, invalid groups. */
- basic_group() ENTT_NOEXCEPT
- : handler{} {}
- /**
- * @brief Returns a const reference to the underlying handler.
- * @return A const reference to the underlying handler.
- */
- const base_type &handle() const ENTT_NOEXCEPT {
- return *handler;
- }
- /**
- * @brief Returns the storage for a given component type.
- * @tparam Comp Type of component of which to return the storage.
- * @return The storage for the given component type.
- */
- template<typename Comp>
- [[nodiscard]] decltype(auto) storage() const ENTT_NOEXCEPT {
- return *std::get<storage_type<Comp> *>(pools);
- }
- /**
- * @brief Returns the storage for a given component type.
- * @tparam Comp Index of component of which to return the storage.
- * @return The storage for the given component type.
- */
- template<std::size_t Comp>
- [[nodiscard]] decltype(auto) storage() const ENTT_NOEXCEPT {
- return *std::get<Comp>(pools);
- }
- /**
- * @brief Returns the number of entities that have the given components.
- * @return Number of entities that have the given components.
- */
- [[nodiscard]] size_type size() const ENTT_NOEXCEPT {
- return *this ? handler->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 ENTT_NOEXCEPT {
- return *this ? handler->capacity() : size_type{};
- }
- /*! @brief Requests the removal of unused capacity. */
- void shrink_to_fit() {
- if(*this) {
- handler->shrink_to_fit();
- }
- }
- /**
- * @brief Checks whether a group is empty.
- * @return True if the group is empty, false otherwise.
- */
- [[nodiscard]] bool empty() const ENTT_NOEXCEPT {
- return !*this || handler->empty();
- }
- /**
- * @brief Returns an iterator to the first entity of the group.
- *
- * The returned iterator points 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 ENTT_NOEXCEPT {
- return *this ? handler->begin() : iterator{};
- }
- /**
- * @brief Returns an iterator that is past the last entity of the group.
- *
- * The returned iterator points to the entity following the last entity of
- * the group. Attempting to dereference the returned iterator results in
- * undefined behavior.
- *
- * @return An iterator to the entity following the last entity of the
- * group.
- */
- [[nodiscard]] iterator end() const ENTT_NOEXCEPT {
- return *this ? handler->end() : iterator{};
- }
- /**
- * @brief Returns an iterator to the first entity of the reversed group.
- *
- * The returned iterator points 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 ENTT_NOEXCEPT {
- return *this ? handler->rbegin() : reverse_iterator{};
- }
- /**
- * @brief Returns an iterator that is past the last entity of the reversed
- * group.
- *
- * The returned iterator points to the entity following the last entity of
- * the reversed group. Attempting to dereference the returned iterator
- * results in undefined behavior.
- *
- * @return An iterator to the entity following the last entity of the
- * reversed group.
- */
- [[nodiscard]] reverse_iterator rend() const ENTT_NOEXCEPT {
- return *this ? handler->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 ENTT_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 ENTT_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 ENTT_NOEXCEPT {
- const auto it = *this ? handler->find(entt) : iterator{};
- return it != end() && *it == entt ? it : end();
- }
- /**
- * @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()[pos];
- }
- /**
- * @brief Checks if a group is properly initialized.
- * @return True if the group is properly initialized, false otherwise.
- */
- [[nodiscard]] explicit operator bool() const ENTT_NOEXCEPT {
- return handler != 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 ENTT_NOEXCEPT {
- return *this && handler->contains(entt);
- }
- /**
- * @brief Returns the components assigned to the given entity.
- *
- * Prefer this function instead of `registry::get` during iterations. It has
- * far better performance than its counterpart.
- *
- * @warning
- * Attempting to use an invalid component type results in a compilation
- * error. Attempting to use an entity that doesn't belong to the group
- * results in undefined behavior.
- *
- * @tparam Comp Types of components to get.
- * @param entt A valid identifier.
- * @return The components assigned to the entity.
- */
- template<typename... Comp>
- [[nodiscard]] decltype(auto) get(const entity_type entt) const {
- ENTT_ASSERT(contains(entt), "Group does not contain entity");
- if constexpr(sizeof...(Comp) == 0) {
- return std::tuple_cat(std::get<storage_type<Get> *>(pools)->get_as_tuple(entt)...);
- } else if constexpr(sizeof...(Comp) == 1) {
- return (std::get<storage_type<Comp> *>(pools)->get(entt), ...);
- } else {
- return std::tuple_cat(std::get<storage_type<Comp> *>(pools)->get_as_tuple(entt)...);
- }
- }
- /**
- * @brief Iterates entities and components 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 components. The
- * _constness_ of the components 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 components. The _constness_ of the
- * components 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 ENTT_NOEXCEPT {
- return handler ? iterable{extended_group_iterator{handler->begin(), pools}, extended_group_iterator{handler->end(), pools}}
- : iterable{extended_group_iterator{{}, pools}, extended_group_iterator{{}, pools}};
- }
- /**
- * @brief Sort a group according to the given comparison function.
- *
- * Sort the group so that iterating it with a couple of iterators returns
- * entities and components in the expected order. See `begin` and `end` for
- * more details.
- *
- * 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<Component &...>, std::tuple<Component &...>);
- * bool(const Component &..., const Component &...);
- * bool(const Entity, const Entity);
- * @endcode
- *
- * Where `Component` 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 Comp Optional types of components 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... Comp, typename Compare, typename Sort = std_sort, typename... Args>
- void sort(Compare compare, Sort algo = Sort{}, Args &&...args) {
- if(*this) {
- if constexpr(sizeof...(Comp) == 0) {
- static_assert(std::is_invocable_v<Compare, const entity_type, const entity_type>, "Invalid comparison function");
- handler->sort(std::move(compare), std::move(algo), std::forward<Args>(args)...);
- } else {
- auto comp = [this, &compare](const entity_type lhs, const entity_type rhs) {
- if constexpr(sizeof...(Comp) == 1) {
- return compare((std::get<storage_type<Comp> *>(pools)->get(lhs), ...), (std::get<storage_type<Comp> *>(pools)->get(rhs), ...));
- } else {
- return compare(std::forward_as_tuple(std::get<storage_type<Comp> *>(pools)->get(lhs)...), std::forward_as_tuple(std::get<storage_type<Comp> *>(pools)->get(rhs)...));
- }
- };
- handler->sort(std::move(comp), std::move(algo), std::forward<Args>(args)...);
- }
- }
- }
- /**
- * @brief Sort the shared pool of entities according to the given component.
- *
- * Non-owning groups of the same type share with the registry a pool of
- * entities with its own order that doesn't depend on the order of any pool
- * of components. Users can order the underlying data structure so that it
- * respects the order of the pool of the given component.
- *
- * @note
- * The shared pool of entities and thus its order is affected by the changes
- * to each and every pool that it tracks. Therefore changes to those pools
- * can quickly ruin the order imposed to the pool of entities shared between
- * the non-owning groups.
- *
- * @tparam Comp Type of component to use to impose the order.
- */
- template<typename Comp>
- void sort() const {
- if(*this) {
- handler->respect(*std::get<storage_type<Comp> *>(pools));
- }
- }
- private:
- base_type *const handler;
- const std::tuple<storage_type<Get> *...> pools;
- };
- /**
- * @brief Owning group.
- *
- * Owning groups return all entities and only the entities that have at least
- * the given components. Moreover:
- *
- * * It's guaranteed that the entity list is tightly packed in memory for fast
- * iterations.
- * * It's guaranteed that the lists of owned components are tightly packed in
- * memory for even faster iterations and to allow direct access.
- * * They stay true to the order of the owned components and all instances have
- * the same order in memory.
- *
- * The more types of components are owned by a group, the faster it is to
- * iterate them.
- *
- * @b Important
- *
- * Iterators aren't invalidated if:
- *
- * * New instances of the given components are created and assigned to entities.
- * * The entity currently pointed is modified (as an example, if one of the
- * given components is removed from the entity to which the iterator points).
- * * The entity currently pointed is destroyed.
- *
- * In all other cases, modifying the pools iterated by the group in any way
- * invalidates all the iterators and using them results in undefined behavior.
- *
- * @note
- * Groups share references to the underlying data structures of the registry
- * that generated them. Therefore any change to the entities and to the
- * components made by means of the registry are immediately reflected by all the
- * groups.
- * Moreover, sorting an owning group affects all the instance of the same group
- * (it means that users don't have to call `sort` on each instance to sort all
- * of them because they share the underlying data structure).
- *
- * @warning
- * Lifetime of a group must not overcome that of the registry that generated it.
- * In any other case, attempting to use a group results in undefined behavior.
- *
- * @tparam Entity A valid entity type (see entt_traits for more details).
- * @tparam Owned Types of components owned by the group.
- * @tparam Get Types of components observed by the group.
- * @tparam Exclude Types of components used to filter the group.
- */
- template<typename Entity, typename... Owned, typename... Get, typename... Exclude>
- class basic_group<Entity, owned_t<Owned...>, get_t<Get...>, exclude_t<Exclude...>> {
- /*! @brief A registry is allowed to create groups. */
- friend class basic_registry<Entity>;
- template<typename Comp>
- using storage_type = constness_as_t<typename storage_traits<Entity, std::remove_const_t<Comp>>::storage_type, Comp>;
- using basic_common_type = std::common_type_t<typename storage_type<Owned>::base_type..., typename storage_type<Get>::base_type...>;
- class extended_group_iterator final {
- template<typename Type>
- auto index_to_element(storage_type<Type> &cpool) const {
- if constexpr(ignore_as_empty_v<std::remove_const_t<Type>>) {
- return std::make_tuple();
- } else {
- return std::forward_as_tuple(cpool.rbegin()[it.index()]);
- }
- }
- public:
- using difference_type = std::ptrdiff_t;
- using value_type = decltype(std::tuple_cat(std::tuple<Entity>{}, std::declval<basic_group>().get({})));
- using pointer = input_iterator_pointer<value_type>;
- using reference = value_type;
- using iterator_category = std::input_iterator_tag;
- extended_group_iterator() = default;
- template<typename... Other>
- extended_group_iterator(typename basic_common_type::iterator from, const std::tuple<storage_type<Owned> *..., storage_type<Get> *...> &cpools)
- : it{from},
- pools{cpools} {}
- extended_group_iterator &operator++() ENTT_NOEXCEPT {
- return ++it, *this;
- }
- extended_group_iterator operator++(int) ENTT_NOEXCEPT {
- extended_group_iterator orig = *this;
- return ++(*this), orig;
- }
- [[nodiscard]] reference operator*() const ENTT_NOEXCEPT {
- return std::tuple_cat(
- std::make_tuple(*it),
- index_to_element<Owned>(*std::get<storage_type<Owned> *>(pools))...,
- std::get<storage_type<Get> *>(pools)->get_as_tuple(*it)...);
- }
- [[nodiscard]] pointer operator->() const ENTT_NOEXCEPT {
- return operator*();
- }
- [[nodiscard]] bool operator==(const extended_group_iterator &other) const ENTT_NOEXCEPT {
- return other.it == it;
- }
- [[nodiscard]] bool operator!=(const extended_group_iterator &other) const ENTT_NOEXCEPT {
- return !(*this == other);
- }
- private:
- typename basic_common_type::iterator it;
- std::tuple<storage_type<Owned> *..., storage_type<Get> *...> pools;
- };
- basic_group(const std::size_t &extent, storage_type<Owned> &...opool, storage_type<Get> &...gpool) ENTT_NOEXCEPT
- : pools{&opool..., &gpool...},
- length{&extent} {}
- public:
- /*! @brief Underlying entity identifier. */
- using entity_type = Entity;
- /*! @brief Unsigned integer type. */
- using size_type = std::size_t;
- /*! @brief Common type among all storage types. */
- using base_type = basic_common_type;
- /*! @brief Random access iterator type. */
- using iterator = typename base_type::iterator;
- /*! @brief Reversed iterator type. */
- using reverse_iterator = typename base_type::reverse_iterator;
- /*! @brief Iterable group type. */
- using iterable = iterable_adaptor<extended_group_iterator>;
- /*! @brief Default constructor to use to create empty, invalid groups. */
- basic_group() ENTT_NOEXCEPT
- : length{} {}
- /**
- * @brief Returns the storage for a given component type.
- * @tparam Comp Type of component of which to return the storage.
- * @return The storage for the given component type.
- */
- template<typename Comp>
- [[nodiscard]] decltype(auto) storage() const ENTT_NOEXCEPT {
- return *std::get<storage_type<Comp> *>(pools);
- }
- /**
- * @brief Returns the storage for a given component type.
- * @tparam Comp Index of component of which to return the storage.
- * @return The storage for the given component type.
- */
- template<std::size_t Comp>
- [[nodiscard]] decltype(auto) storage() const ENTT_NOEXCEPT {
- return *std::get<Comp>(pools);
- }
- /**
- * @brief Returns the number of entities that have the given components.
- * @return Number of entities that have the given components.
- */
- [[nodiscard]] size_type size() const ENTT_NOEXCEPT {
- return *this ? *length : size_type{};
- }
- /**
- * @brief Checks whether a group is empty.
- * @return True if the group is empty, false otherwise.
- */
- [[nodiscard]] bool empty() const ENTT_NOEXCEPT {
- return !*this || !*length;
- }
- /**
- * @brief Returns an iterator to the first entity of the group.
- *
- * The returned iterator points 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 ENTT_NOEXCEPT {
- return *this ? (std::get<0>(pools)->base_type::end() - *length) : iterator{};
- }
- /**
- * @brief Returns an iterator that is past the last entity of the group.
- *
- * The returned iterator points to the entity following the last entity of
- * the group. Attempting to dereference the returned iterator results in
- * undefined behavior.
- *
- * @return An iterator to the entity following the last entity of the
- * group.
- */
- [[nodiscard]] iterator end() const ENTT_NOEXCEPT {
- return *this ? std::get<0>(pools)->base_type::end() : iterator{};
- }
- /**
- * @brief Returns an iterator to the first entity of the reversed group.
- *
- * The returned iterator points 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 ENTT_NOEXCEPT {
- return *this ? std::get<0>(pools)->base_type::rbegin() : reverse_iterator{};
- }
- /**
- * @brief Returns an iterator that is past the last entity of the reversed
- * group.
- *
- * The returned iterator points to the entity following the last entity of
- * the reversed group. Attempting to dereference the returned iterator
- * results in undefined behavior.
- *
- * @return An iterator to the entity following the last entity of the
- * reversed group.
- */
- [[nodiscard]] reverse_iterator rend() const ENTT_NOEXCEPT {
- return *this ? (std::get<0>(pools)->base_type::rbegin() + *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 ENTT_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 ENTT_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 ENTT_NOEXCEPT {
- const auto it = *this ? std::get<0>(pools)->find(entt) : iterator{};
- return it != end() && it >= begin() && *it == entt ? it : end();
- }
- /**
- * @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()[pos];
- }
- /**
- * @brief Checks if a group is properly initialized.
- * @return True if the group is properly initialized, false otherwise.
- */
- [[nodiscard]] explicit operator bool() const ENTT_NOEXCEPT {
- return length != 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 ENTT_NOEXCEPT {
- return *this && std::get<0>(pools)->contains(entt) && (std::get<0>(pools)->index(entt) < (*length));
- }
- /**
- * @brief Returns the components assigned to the given entity.
- *
- * Prefer this function instead of `registry::get` during iterations. It has
- * far better performance than its counterpart.
- *
- * @warning
- * Attempting to use an invalid component type results in a compilation
- * error. Attempting to use an entity that doesn't belong to the group
- * results in undefined behavior.
- *
- * @tparam Comp Types of components to get.
- * @param entt A valid identifier.
- * @return The components assigned to the entity.
- */
- template<typename... Comp>
- [[nodiscard]] decltype(auto) get(const entity_type entt) const {
- ENTT_ASSERT(contains(entt), "Group does not contain entity");
- if constexpr(sizeof...(Comp) == 0) {
- return std::tuple_cat(std::get<storage_type<Owned> *>(pools)->get_as_tuple(entt)..., std::get<storage_type<Get> *>(pools)->get_as_tuple(entt)...);
- } else if constexpr(sizeof...(Comp) == 1) {
- return (std::get<storage_type<Comp> *>(pools)->get(entt), ...);
- } else {
- return std::tuple_cat(std::get<storage_type<Comp> *>(pools)->get_as_tuple(entt)...);
- }
- }
- /**
- * @brief Iterates entities and components 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 components. The
- * _constness_ of the components 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 components. The _constness_ of the
- * components 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 ENTT_NOEXCEPT {
- iterator last = length ? std::get<0>(pools)->basic_common_type::end() : iterator{};
- return {extended_group_iterator{last - *length, pools}, extended_group_iterator{last, pools}};
- }
- /**
- * @brief Sort a group according to the given comparison function.
- *
- * Sort the group so that iterating it with a couple of iterators returns
- * entities and components in the expected order. See `begin` and `end` for
- * more details.
- *
- * 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<Component &...>, std::tuple<Component &...>);
- * bool(const Component &, const Component &);
- * bool(const Entity, const Entity);
- * @endcode
- *
- * Where `Component` 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 Comp Optional types of components 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... Comp, typename Compare, typename Sort = std_sort, typename... Args>
- void sort(Compare compare, Sort algo = Sort{}, Args &&...args) const {
- auto *cpool = std::get<0>(pools);
- if constexpr(sizeof...(Comp) == 0) {
- static_assert(std::is_invocable_v<Compare, const entity_type, const entity_type>, "Invalid comparison function");
- cpool->sort_n(*length, std::move(compare), std::move(algo), std::forward<Args>(args)...);
- } else {
- auto comp = [this, &compare](const entity_type lhs, const entity_type rhs) {
- if constexpr(sizeof...(Comp) == 1) {
- return compare((std::get<storage_type<Comp> *>(pools)->get(lhs), ...), (std::get<storage_type<Comp> *>(pools)->get(rhs), ...));
- } else {
- return compare(std::forward_as_tuple(std::get<storage_type<Comp> *>(pools)->get(lhs)...), std::forward_as_tuple(std::get<storage_type<Comp> *>(pools)->get(rhs)...));
- }
- };
- cpool->sort_n(*length, std::move(comp), std::move(algo), std::forward<Args>(args)...);
- }
- [this](auto *head, auto *...other) {
- for(auto next = *length; next; --next) {
- const auto pos = next - 1;
- [[maybe_unused]] const auto entt = head->data()[pos];
- (other->swap_elements(other->data()[pos], entt), ...);
- }
- }(std::get<storage_type<Owned> *>(pools)...);
- }
- private:
- const std::tuple<storage_type<Owned> *..., storage_type<Get> *...> pools;
- const size_type *const length;
- };
- } // namespace entt
- #endif
- // #include "entity/handle.hpp"
- #ifndef ENTT_ENTITY_HANDLE_HPP
- #define ENTT_ENTITY_HANDLE_HPP
- #include <tuple>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- // #include "../core/type_traits.hpp"
- // #include "fwd.hpp"
- // #include "registry.hpp"
- #ifndef ENTT_ENTITY_REGISTRY_HPP
- #define ENTT_ENTITY_REGISTRY_HPP
- #include <algorithm>
- #include <cstddef>
- #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 <algorithm>
- #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
- #define ENTT_STR(arg) #arg
- #define ENTT_XSTR(arg) ENTT_STR(arg)
- #endif
- #define ENTT_VERSION_MAJOR 3
- #define ENTT_VERSION_MINOR 10
- #define ENTT_VERSION_PATCH 3
- #define ENTT_VERSION \
- ENTT_XSTR(ENTT_VERSION_MAJOR) \
- "." ENTT_XSTR(ENTT_VERSION_MINOR) "." ENTT_XSTR(ENTT_VERSION_PATCH)
- #endif
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #ifndef ENTT_NOEXCEPT
- # define ENTT_NOEXCEPT noexcept
- # define ENTT_NOEXCEPT_IF(expr) noexcept(expr)
- # else
- # define ENTT_NOEXCEPT_IF(...)
- #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
- #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(...) (void(0))
- #elif !defined ENTT_ASSERT
- # include <cassert>
- # define ENTT_ASSERT(condition, ...) assert(condition)
- #endif
- #ifdef ENTT_NO_ETO
- # define ENTT_IGNORE_IF_EMPTY false
- #else
- # define ENTT_IGNORE_IF_EMPTY true
- #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
- #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
- #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 "../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
- #define ENTT_STR(arg) #arg
- #define ENTT_XSTR(arg) ENTT_STR(arg)
- #endif
- #define ENTT_VERSION_MAJOR 3
- #define ENTT_VERSION_MINOR 10
- #define ENTT_VERSION_PATCH 3
- #define ENTT_VERSION \
- ENTT_XSTR(ENTT_VERSION_MAJOR) \
- "." ENTT_XSTR(ENTT_VERSION_MINOR) "." ENTT_XSTR(ENTT_VERSION_PATCH)
- #endif
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #ifndef ENTT_NOEXCEPT
- # define ENTT_NOEXCEPT noexcept
- # define ENTT_NOEXCEPT_IF(expr) noexcept(expr)
- # else
- # define ENTT_NOEXCEPT_IF(...)
- #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
- #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(...) (void(0))
- #elif !defined ENTT_ASSERT
- # include <cassert>
- # define ENTT_ASSERT(condition, ...) assert(condition)
- #endif
- #ifdef ENTT_NO_ETO
- # define ENTT_IGNORE_IF_EMPTY false
- #else
- # define ENTT_IGNORE_IF_EMPTY true
- #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
- #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
- #endif
- // #include "type_traits.hpp"
- #ifndef ENTT_CORE_TYPE_TRAITS_HPP
- #define ENTT_CORE_TYPE_TRAITS_HPP
- #include <cstddef>
- #include <iterator>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- // #include "fwd.hpp"
- #ifndef ENTT_CORE_FWD_HPP
- #define ENTT_CORE_FWD_HPP
- #include <cstdint>
- #include <type_traits>
- // #include "../config/config.h"
- namespace entt {
- template<std::size_t Len = sizeof(double[2]), std::size_t = alignof(typename std::aligned_storage_t<Len + !Len>)>
- 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<>;
- } // 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.
- * @tparam The size of the type if `sizeof` accepts it, 0 otherwise.
- */
- 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))>>
- : 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 Type First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<std::size_t Index, typename Type, typename... Other>
- struct type_list_element<Index, type_list<Type, Other...>>
- : type_list_element<Index - 1u, type_list<Other...>> {};
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam Type First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<typename Type, typename... Other>
- struct type_list_element<0u, type_list<Type, Other...>> {
- /*! @brief Searched type. */
- using type = Type;
- };
- /**
- * @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 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;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename>
- struct type_list_unique;
- /**
- * @brief Removes duplicates types from a type list.
- * @tparam Type One of the types provided by the given type list.
- * @tparam Other The other types provided by the given type list.
- */
- template<typename Type, typename... Other>
- struct type_list_unique<type_list<Type, Other...>> {
- /*! @brief A type list without duplicate types. */
- using type = std::conditional_t<
- (std::is_same_v<Type, Other> || ...),
- typename type_list_unique<type_list<Other...>>::type,
- type_list_cat_t<type_list<Type>, typename type_list_unique<type_list<Other...>>::type>>;
- };
- /*! @brief Removes duplicates types from a type list. */
- template<>
- struct type_list_unique<type_list<>> {
- /*! @brief A type list without duplicate types. */
- using type = type_list<>;
- };
- /**
- * @brief Helper type.
- * @tparam Type A type list.
- */
- template<typename Type>
- using type_list_unique_t = typename type_list_unique<Type>::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::disjunction<std::is_same<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 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 value. */
- static constexpr auto value = Value;
- };
- /**
- * @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 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 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
- * Internal details not to be documented.
- */
- 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
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /*! @copydoc is_iterator */
- template<typename Type>
- struct is_iterator<Type, std::enable_if_t<!std::is_same_v<std::remove_const_t<std::remove_pointer_t<Type>>, void>>>
- : 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::conjunction<std::is_empty<Type>, std::negation<std::is_final<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;
- /**
- * @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, typename = void>
- struct is_equality_comparable: std::false_type {};
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- 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 Type, std::size_t... Index>
- [[nodiscard]] constexpr bool unpack_maybe_equality_comparable(std::index_sequence<Index...>) {
- return (is_equality_comparable<std::tuple_element_t<Index, Type>>::value && ...);
- }
- template<typename>
- [[nodiscard]] constexpr bool maybe_equality_comparable(choice_t<0>) {
- return true;
- }
- template<typename Type>
- [[nodiscard]] constexpr auto maybe_equality_comparable(choice_t<1>) -> decltype(std::declval<typename Type::value_type>(), bool{}) {
- if constexpr(is_iterator_v<Type>) {
- return true;
- } else if constexpr(std::is_same_v<typename Type::value_type, Type>) {
- return maybe_equality_comparable<Type>(choice<0>);
- } else {
- return is_equality_comparable<typename Type::value_type>::value;
- }
- }
- template<typename Type>
- [[nodiscard]] constexpr std::enable_if_t<is_complete_v<std::tuple_size<std::remove_const_t<Type>>>, bool> maybe_equality_comparable(choice_t<2>) {
- if constexpr(has_tuple_size_value<Type>::value) {
- return unpack_maybe_equality_comparable<Type>(std::make_index_sequence<std::tuple_size<Type>::value>{});
- } else {
- return maybe_equality_comparable<Type>(choice<1>);
- }
- }
- } // namespace internal
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /*! @copydoc is_equality_comparable */
- template<typename Type>
- struct is_equality_comparable<Type, std::void_t<decltype(std::declval<Type>() == std::declval<Type>())>>
- : std::bool_constant<internal::maybe_equality_comparable<Type>(choice<2>)> {};
- /**
- * @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 = std::add_const_t<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;
- } // namespace entt
- #endif
- namespace entt {
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- namespace internal {
- template<typename Type, std::size_t, typename = void>
- struct compressed_pair_element {
- using reference = Type &;
- using const_reference = const Type &;
- template<bool Dummy = true, typename = std::enable_if_t<Dummy && std::is_default_constructible_v<Type>>>
- compressed_pair_element()
- : value{} {}
- template<typename Args, typename = std::enable_if_t<!std::is_same_v<std::remove_cv_t<std::remove_reference_t<Args>>, compressed_pair_element>>>
- compressed_pair_element(Args &&args)
- : value{std::forward<Args>(args)} {}
- template<typename... Args, std::size_t... Index>
- compressed_pair_element(std::tuple<Args...> args, std::index_sequence<Index...>)
- : value{std::forward<Args>(std::get<Index>(args))...} {}
- [[nodiscard]] reference get() ENTT_NOEXCEPT {
- return value;
- }
- [[nodiscard]] const_reference get() const ENTT_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<bool Dummy = true, typename = std::enable_if_t<Dummy && std::is_default_constructible_v<base_type>>>
- compressed_pair_element()
- : base_type{} {}
- template<typename Args, typename = std::enable_if_t<!std::is_same_v<std::remove_cv_t<std::remove_reference_t<Args>>, compressed_pair_element>>>
- compressed_pair_element(Args &&args)
- : base_type{std::forward<Args>(args)} {}
- template<typename... Args, std::size_t... Index>
- compressed_pair_element(std::tuple<Args...> args, std::index_sequence<Index...>)
- : base_type{std::forward<Args>(std::get<Index>(args))...} {}
- [[nodiscard]] reference get() ENTT_NOEXCEPT {
- return *this;
- }
- [[nodiscard]] const_reference get() const ENTT_NOEXCEPT {
- return *this;
- }
- };
- } // namespace internal
- /**
- * Internal details not to be documented.
- * @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()
- : 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) = 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)
- : 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)
- : first_base{std::move(args), std::index_sequence_for<Args...>{}},
- second_base{std::move(other), std::index_sequence_for<Other...>{}} {}
- /**
- * @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) = default;
- /**
- * @brief Returns the first element that a pair stores.
- * @return The first element that a pair stores.
- */
- [[nodiscard]] first_type &first() ENTT_NOEXCEPT {
- return static_cast<first_base &>(*this).get();
- }
- /*! @copydoc first */
- [[nodiscard]] const first_type &first() const ENTT_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]] second_type &second() ENTT_NOEXCEPT {
- return static_cast<second_base &>(*this).get();
- }
- /*! @copydoc second */
- [[nodiscard]] const second_type &second() const ENTT_NOEXCEPT {
- return static_cast<const second_base &>(*this).get();
- }
- /**
- * @brief Swaps two compressed pair objects.
- * @param other The compressed pair to swap with.
- */
- void swap(compressed_pair &other) {
- 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>
- decltype(auto) get() ENTT_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>
- decltype(auto) get() const ENTT_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>
- inline void swap(compressed_pair<First, Second> &lhs, compressed_pair<First, Second> &rhs) {
- lhs.swap(rhs);
- }
- } // namespace entt
- // disable structured binding support for clang 6, it messes when specializing tuple_size
- #if !defined __clang_major__ || __clang_major__ > 6
- 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
- #endif
- // #include "../core/iterator.hpp"
- #ifndef ENTT_CORE_ITERATOR_HPP
- #define ENTT_CORE_ITERATOR_HPP
- #include <iterator>
- #include <memory>
- #include <utility>
- // #include "../config/config.h"
- 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 Pointer type. */
- using pointer = Type *;
- /*! @brief Default copy constructor, deleted on purpose. */
- input_iterator_pointer(const input_iterator_pointer &) = delete;
- /*! @brief Default move constructor. */
- input_iterator_pointer(input_iterator_pointer &&) = default;
- /**
- * @brief Constructs a proxy object by move.
- * @param val Value to use to initialize the proxy object.
- */
- input_iterator_pointer(Type &&val)
- : value{std::move(val)} {}
- /**
- * @brief Default copy assignment operator, deleted on purpose.
- * @return This proxy object.
- */
- input_iterator_pointer &operator=(const input_iterator_pointer &) = delete;
- /**
- * @brief Default move assignment operator.
- * @return This proxy object.
- */
- input_iterator_pointer &operator=(input_iterator_pointer &&) = default;
- /**
- * @brief Access operator for accessing wrapped values.
- * @return A pointer to the wrapped value.
- */
- [[nodiscard]] pointer operator->() ENTT_NOEXCEPT {
- return std::addressof(value);
- }
- private:
- Type value;
- };
- /**
- * @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. */
- iterable_adaptor() = default;
- /**
- * @brief Creates an iterable object from a pair of iterators.
- * @param from Begin iterator.
- * @param to End iterator.
- */
- iterable_adaptor(iterator from, sentinel to)
- : first{from},
- last{to} {}
- /**
- * @brief Returns an iterator to the beginning.
- * @return An iterator to the first element of the range.
- */
- [[nodiscard]] iterator begin() const ENTT_NOEXCEPT {
- return first;
- }
- /**
- * @brief Returns an iterator to the end.
- * @return An iterator to the element following the last element of the
- * range.
- */
- [[nodiscard]] sentinel end() const ENTT_NOEXCEPT {
- return last;
- }
- /*! @copydoc begin */
- [[nodiscard]] iterator cbegin() const ENTT_NOEXCEPT {
- return begin();
- }
- /*! @copydoc end */
- [[nodiscard]] sentinel cend() const ENTT_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 <limits>
- #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) ENTT_NOEXCEPT {
- if constexpr(std::is_pointer_v<std::remove_cv_t<std::remove_reference_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) ENTT_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) ENTT_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) ENTT_NOEXCEPT {
- ENTT_ASSERT(std::allocator_traits<Allocator>::propagate_on_container_swap::value || lhs == rhs, "Cannot swap the containers");
- if constexpr(std::allocator_traits<Allocator>::propagate_on_container_swap::value) {
- using std::swap;
- swap(lhs, rhs);
- }
- }
- /**
- * @brief Checks whether a value is a power of two or not.
- * @param value A value that may or may not be a power of two.
- * @return True if the value is a power of two, false otherwise.
- */
- [[nodiscard]] inline constexpr bool is_power_of_two(const std::size_t value) ENTT_NOEXCEPT {
- return value && ((value & (value - 1)) == 0);
- }
- /**
- * @brief Computes the smallest power of two greater than or equal to a value.
- * @param value The value to use.
- * @return The smallest power of two greater than or equal to the given value.
- */
- [[nodiscard]] inline constexpr std::size_t next_power_of_two(const std::size_t value) ENTT_NOEXCEPT {
- ENTT_ASSERT(value < (std::size_t{1u} << (std::numeric_limits<std::size_t>::digits - 1)), "Numeric limits exceeded");
- std::size_t curr = value - (value != 0u);
- for(int next = 1; next < std::numeric_limits<std::size_t>::digits; next = next * 2) {
- curr |= curr >> next;
- }
- return ++curr;
- }
- /**
- * @brief Fast module utility function (powers of two only).
- * @param value A value for which to calculate the modulus.
- * @param mod _Modulus_, it must be a power of two.
- * @return The common remainder.
- */
- [[nodiscard]] inline constexpr std::size_t fast_mod(const std::size_t value, const std::size_t mod) ENTT_NOEXCEPT {
- ENTT_ASSERT(is_power_of_two(mod), "Value must be a power of two");
- return value & (mod - 1u);
- }
- /**
- * @brief Deleter for allocator-aware unique pointers (waiting for C++20).
- * @tparam Args Types of arguments to use to construct the object.
- */
- 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.
- */
- allocation_deleter(const allocator_type &alloc)
- : Allocator{alloc} {}
- /**
- * @brief Destroys the pointed object and deallocates its memory.
- * @param ptr A valid pointer to an object of the given type.
- */
- void operator()(pointer ptr) {
- using alloc_traits = typename 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>
- 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
- * Internal details not to be documented.
- */
- 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) ENTT_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) ENTT_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) ENTT_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) ENTT_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) ENTT_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) ENTT_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
- /**
- * Internal details not to be documented.
- * @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) ENTT_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([&](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 <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.
- * @tparam The size of the type if `sizeof` accepts it, 0 otherwise.
- */
- 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))>>
- : 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 Type First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<std::size_t Index, typename Type, typename... Other>
- struct type_list_element<Index, type_list<Type, Other...>>
- : type_list_element<Index - 1u, type_list<Other...>> {};
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam Type First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<typename Type, typename... Other>
- struct type_list_element<0u, type_list<Type, Other...>> {
- /*! @brief Searched type. */
- using type = Type;
- };
- /**
- * @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 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;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename>
- struct type_list_unique;
- /**
- * @brief Removes duplicates types from a type list.
- * @tparam Type One of the types provided by the given type list.
- * @tparam Other The other types provided by the given type list.
- */
- template<typename Type, typename... Other>
- struct type_list_unique<type_list<Type, Other...>> {
- /*! @brief A type list without duplicate types. */
- using type = std::conditional_t<
- (std::is_same_v<Type, Other> || ...),
- typename type_list_unique<type_list<Other...>>::type,
- type_list_cat_t<type_list<Type>, typename type_list_unique<type_list<Other...>>::type>>;
- };
- /*! @brief Removes duplicates types from a type list. */
- template<>
- struct type_list_unique<type_list<>> {
- /*! @brief A type list without duplicate types. */
- using type = type_list<>;
- };
- /**
- * @brief Helper type.
- * @tparam Type A type list.
- */
- template<typename Type>
- using type_list_unique_t = typename type_list_unique<Type>::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::disjunction<std::is_same<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 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 value. */
- static constexpr auto value = Value;
- };
- /**
- * @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 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 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
- * Internal details not to be documented.
- */
- 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
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /*! @copydoc is_iterator */
- template<typename Type>
- struct is_iterator<Type, std::enable_if_t<!std::is_same_v<std::remove_const_t<std::remove_pointer_t<Type>>, void>>>
- : 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::conjunction<std::is_empty<Type>, std::negation<std::is_final<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;
- /**
- * @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, typename = void>
- struct is_equality_comparable: std::false_type {};
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- 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 Type, std::size_t... Index>
- [[nodiscard]] constexpr bool unpack_maybe_equality_comparable(std::index_sequence<Index...>) {
- return (is_equality_comparable<std::tuple_element_t<Index, Type>>::value && ...);
- }
- template<typename>
- [[nodiscard]] constexpr bool maybe_equality_comparable(choice_t<0>) {
- return true;
- }
- template<typename Type>
- [[nodiscard]] constexpr auto maybe_equality_comparable(choice_t<1>) -> decltype(std::declval<typename Type::value_type>(), bool{}) {
- if constexpr(is_iterator_v<Type>) {
- return true;
- } else if constexpr(std::is_same_v<typename Type::value_type, Type>) {
- return maybe_equality_comparable<Type>(choice<0>);
- } else {
- return is_equality_comparable<typename Type::value_type>::value;
- }
- }
- template<typename Type>
- [[nodiscard]] constexpr std::enable_if_t<is_complete_v<std::tuple_size<std::remove_const_t<Type>>>, bool> maybe_equality_comparable(choice_t<2>) {
- if constexpr(has_tuple_size_value<Type>::value) {
- return unpack_maybe_equality_comparable<Type>(std::make_index_sequence<std::tuple_size<Type>::value>{});
- } else {
- return maybe_equality_comparable<Type>(choice<1>);
- }
- }
- } // namespace internal
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /*! @copydoc is_equality_comparable */
- template<typename Type>
- struct is_equality_comparable<Type, std::void_t<decltype(std::declval<Type>() == std::declval<Type>())>>
- : std::bool_constant<internal::maybe_equality_comparable<Type>(choice<2>)> {};
- /**
- * @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 = std::add_const_t<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;
- } // namespace entt
- #endif
- // #include "fwd.hpp"
- #ifndef ENTT_CONTAINER_FWD_HPP
- #define ENTT_CONTAINER_FWD_HPP
- #include <functional>
- #include <memory>
- namespace entt {
- template<
- typename Key,
- typename Type,
- typename = std::hash<Key>,
- typename = std::equal_to<Key>,
- typename = std::allocator<std::pair<const Key, Type>>>
- class dense_map;
- template<
- typename Type,
- typename = std::hash<Type>,
- typename = std::equal_to<Type>,
- typename = std::allocator<Type>>
- class dense_set;
- } // namespace entt
- #endif
- namespace entt {
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- namespace internal {
- 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;
- dense_map_iterator() ENTT_NOEXCEPT
- : it{} {}
- dense_map_iterator(const It iter) ENTT_NOEXCEPT
- : it{iter} {}
- template<typename Other, typename = std::enable_if_t<!std::is_same_v<It, Other> && std::is_constructible_v<It, Other>>>
- dense_map_iterator(const dense_map_iterator<Other> &other) ENTT_NOEXCEPT
- : it{other.it} {}
- dense_map_iterator &operator++() ENTT_NOEXCEPT {
- return ++it, *this;
- }
- dense_map_iterator operator++(int) ENTT_NOEXCEPT {
- dense_map_iterator orig = *this;
- return ++(*this), orig;
- }
- dense_map_iterator &operator--() ENTT_NOEXCEPT {
- return --it, *this;
- }
- dense_map_iterator operator--(int) ENTT_NOEXCEPT {
- dense_map_iterator orig = *this;
- return operator--(), orig;
- }
- dense_map_iterator &operator+=(const difference_type value) ENTT_NOEXCEPT {
- it += value;
- return *this;
- }
- dense_map_iterator operator+(const difference_type value) const ENTT_NOEXCEPT {
- dense_map_iterator copy = *this;
- return (copy += value);
- }
- dense_map_iterator &operator-=(const difference_type value) ENTT_NOEXCEPT {
- return (*this += -value);
- }
- dense_map_iterator operator-(const difference_type value) const ENTT_NOEXCEPT {
- return (*this + -value);
- }
- [[nodiscard]] reference operator[](const difference_type value) const ENTT_NOEXCEPT {
- return {it[value].element.first, it[value].element.second};
- }
- [[nodiscard]] pointer operator->() const ENTT_NOEXCEPT {
- return operator*();
- }
- [[nodiscard]] reference operator*() const ENTT_NOEXCEPT {
- return {it->element.first, it->element.second};
- }
- template<typename ILhs, typename IRhs>
- friend std::ptrdiff_t operator-(const dense_map_iterator<ILhs> &, const dense_map_iterator<IRhs> &) ENTT_NOEXCEPT;
- template<typename ILhs, typename IRhs>
- friend bool operator==(const dense_map_iterator<ILhs> &, const dense_map_iterator<IRhs> &) ENTT_NOEXCEPT;
- template<typename ILhs, typename IRhs>
- friend bool operator<(const dense_map_iterator<ILhs> &, const dense_map_iterator<IRhs> &) ENTT_NOEXCEPT;
- private:
- It it;
- };
- template<typename ILhs, typename IRhs>
- [[nodiscard]] std::ptrdiff_t operator-(const dense_map_iterator<ILhs> &lhs, const dense_map_iterator<IRhs> &rhs) ENTT_NOEXCEPT {
- return lhs.it - rhs.it;
- }
- template<typename ILhs, typename IRhs>
- [[nodiscard]] bool operator==(const dense_map_iterator<ILhs> &lhs, const dense_map_iterator<IRhs> &rhs) ENTT_NOEXCEPT {
- return lhs.it == rhs.it;
- }
- template<typename ILhs, typename IRhs>
- [[nodiscard]] bool operator!=(const dense_map_iterator<ILhs> &lhs, const dense_map_iterator<IRhs> &rhs) ENTT_NOEXCEPT {
- return !(lhs == rhs);
- }
- template<typename ILhs, typename IRhs>
- [[nodiscard]] bool operator<(const dense_map_iterator<ILhs> &lhs, const dense_map_iterator<IRhs> &rhs) ENTT_NOEXCEPT {
- return lhs.it < rhs.it;
- }
- template<typename ILhs, typename IRhs>
- [[nodiscard]] bool operator>(const dense_map_iterator<ILhs> &lhs, const dense_map_iterator<IRhs> &rhs) ENTT_NOEXCEPT {
- return rhs < lhs;
- }
- template<typename ILhs, typename IRhs>
- [[nodiscard]] bool operator<=(const dense_map_iterator<ILhs> &lhs, const dense_map_iterator<IRhs> &rhs) ENTT_NOEXCEPT {
- return !(lhs > rhs);
- }
- template<typename ILhs, typename IRhs>
- [[nodiscard]] bool operator>=(const dense_map_iterator<ILhs> &lhs, const dense_map_iterator<IRhs> &rhs) ENTT_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;
- dense_map_local_iterator() ENTT_NOEXCEPT
- : it{},
- offset{} {}
- dense_map_local_iterator(It iter, const std::size_t pos) ENTT_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>>>
- dense_map_local_iterator(const dense_map_local_iterator<Other> &other) ENTT_NOEXCEPT
- : it{other.it},
- offset{other.offset} {}
- dense_map_local_iterator &operator++() ENTT_NOEXCEPT {
- return offset = it[offset].next, *this;
- }
- dense_map_local_iterator operator++(int) ENTT_NOEXCEPT {
- dense_map_local_iterator orig = *this;
- return ++(*this), orig;
- }
- [[nodiscard]] pointer operator->() const ENTT_NOEXCEPT {
- return operator*();
- }
- [[nodiscard]] reference operator*() const ENTT_NOEXCEPT {
- return {it[offset].element.first, it[offset].element.second};
- }
- [[nodiscard]] std::size_t index() const ENTT_NOEXCEPT {
- return offset;
- }
- private:
- It it;
- std::size_t offset;
- };
- template<typename ILhs, typename IRhs>
- [[nodiscard]] bool operator==(const dense_map_local_iterator<ILhs> &lhs, const dense_map_local_iterator<IRhs> &rhs) ENTT_NOEXCEPT {
- return lhs.index() == rhs.index();
- }
- template<typename ILhs, typename IRhs>
- [[nodiscard]] bool operator!=(const dense_map_local_iterator<ILhs> &lhs, const dense_map_local_iterator<IRhs> &rhs) ENTT_NOEXCEPT {
- return !(lhs == rhs);
- }
- } // namespace internal
- /**
- * Internal details not to be documented.
- * @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;
- using node_type = internal::dense_map_node<Key, Type>;
- using alloc_traits = typename 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 ENTT_NOEXCEPT {
- return fast_mod(sparse.second()(key), bucket_count());
- }
- template<typename Other>
- [[nodiscard]] auto constrained_find(const Other &key, std::size_t bucket) {
- for(auto it = begin(bucket), last = end(bucket); it != last; ++it) {
- if(packed.second()(it->first, key)) {
- return begin() + static_cast<typename iterator::difference_type>(it.index());
- }
- }
- return end();
- }
- template<typename Other>
- [[nodiscard]] auto constrained_find(const Other &key, std::size_t bucket) const {
- for(auto it = cbegin(bucket), last = cend(bucket); it != last; ++it) {
- if(packed.second()(it->first, key)) {
- return cbegin() + static_cast<typename iterator::difference_type>(it.index());
- }
- }
- 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) {
- packed.first()[pos] = std::move(packed.first().back());
- size_type *curr = sparse.first().data() + key_to_bucket(packed.first().back().element.first);
- for(; *curr != last; curr = &packed.first()[*curr].next) {}
- *curr = pos;
- }
- packed.first().pop_back();
- }
- void rehash_if_required() {
- if(size() > (bucket_count() * max_load_factor())) {
- rehash(bucket_count() * 2u);
- }
- }
- public:
- /*! @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 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 Allocator type. */
- using allocator_type = Allocator;
- /*! @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 bucket_count Minimal number of buckets.
- * @param allocator The allocator to use.
- */
- dense_map(const size_type bucket_count, const allocator_type &allocator)
- : dense_map{bucket_count, hasher{}, key_equal{}, allocator} {}
- /**
- * @brief Constructs an empty container with a given allocator, hash
- * function and user supplied minimal number of buckets.
- * @param bucket_count Minimal number of buckets.
- * @param hash Hash function to use.
- * @param allocator The allocator to use.
- */
- dense_map(const size_type bucket_count, const hasher &hash, const allocator_type &allocator)
- : dense_map{bucket_count, 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 bucket_count 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 bucket_count, const hasher &hash = hasher{}, const key_equal &equal = key_equal{}, const allocator_type &allocator = allocator_type{})
- : sparse{allocator, hash},
- packed{allocator, equal},
- threshold{default_threshold} {
- rehash(bucket_count);
- }
- /*! @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 &&) = 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 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 &&) = default;
- /**
- * @brief Returns the associated allocator.
- * @return The associated allocator.
- */
- [[nodiscard]] constexpr allocator_type get_allocator() const ENTT_NOEXCEPT {
- return sparse.first().get_allocator();
- }
- /**
- * @brief Returns an iterator to the beginning.
- *
- * The returned iterator points to the first instance of the internal array.
- * 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 ENTT_NOEXCEPT {
- return packed.first().begin();
- }
- /*! @copydoc cbegin */
- [[nodiscard]] const_iterator begin() const ENTT_NOEXCEPT {
- return cbegin();
- }
- /*! @copydoc begin */
- [[nodiscard]] iterator begin() ENTT_NOEXCEPT {
- return packed.first().begin();
- }
- /**
- * @brief Returns an iterator to the end.
- *
- * The returned iterator points to the element following the last instance
- * of the internal array. Attempting to dereference the returned iterator
- * results in undefined behavior.
- *
- * @return An iterator to the element following the last instance of the
- * internal array.
- */
- [[nodiscard]] const_iterator cend() const ENTT_NOEXCEPT {
- return packed.first().end();
- }
- /*! @copydoc cend */
- [[nodiscard]] const_iterator end() const ENTT_NOEXCEPT {
- return cend();
- }
- /*! @copydoc end */
- [[nodiscard]] iterator end() ENTT_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 ENTT_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 ENTT_NOEXCEPT {
- return packed.first().size();
- }
- /*! @brief Clears the container. */
- void clear() ENTT_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()[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().data() + key_to_bucket(key); *curr != (std::numeric_limits<size_type>::max)(); 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 Exchanges the contents with those of a given container.
- * @param other Container to exchange the content with.
- */
- void swap(dense_map &other) {
- using std::swap;
- swap(sparse, other.sparse);
- swap(packed, other.packed);
- swap(threshold, other.threshold);
- }
- /**
- * @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 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 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
- * 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 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 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 {packed.first().begin(), (std::numeric_limits<size_type>::max)()};
- }
- /**
- * @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([[maybe_unused]] 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 {packed.first().begin(), (std::numeric_limits<size_type>::max)()};
- }
- /**
- * @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 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 count New number of buckets.
- */
- void rehash(const size_type count) {
- auto value = (std::max)(count, minimum_capacity);
- value = (std::max)(value, static_cast<size_type>(size() / max_load_factor()));
- if(const auto sz = next_power_of_two(value); sz != bucket_count()) {
- sparse.first().resize(sz);
- std::fill(sparse.first().begin(), sparse.first().end(), (std::numeric_limits<size_type>::max)());
- 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 count New number of elements.
- */
- void reserve(const size_type count) {
- packed.first().reserve(count);
- rehash(static_cast<size_type>(std::ceil(count / 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;
- };
- } // namespace entt
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- 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
- /**
- * Internal details not to be documented.
- * @endcond
- */
- #endif
- // #include "../core/algorithm.hpp"
- // #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"
- #ifndef ENTT_CORE_UTILITY_HPP
- #define ENTT_CORE_UTILITY_HPP
- #include <utility>
- // #include "../config/config.h"
- 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<class Type>
- [[nodiscard]] constexpr Type &&operator()(Type &&value) const ENTT_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) ENTT_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) ENTT_NOEXCEPT {
- return func;
- }
- /**
- * @brief Helper type for visitors.
- * @tparam Func Types of function objects.
- */
- template<class... Func>
- struct overloaded: Func... {
- using Func::operator()...;
- };
- /**
- * @brief Deduction guide.
- * @tparam Func Types of function objects.
- */
- template<class... Func>
- overloaded(Func...) -> overloaded<Func...>;
- /**
- * @brief Basic implementation of a y-combinator.
- * @tparam Func Type of a potentially recursive function.
- */
- template<class Func>
- struct y_combinator {
- /**
- * @brief Constructs a y-combinator from a given function.
- * @param recursive A potentially recursive function.
- */
- y_combinator(Func recursive)
- : 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<class... Args>
- decltype(auto) operator()(Args &&...args) const {
- return func(*this, std::forward<Args>(args)...);
- }
- /*! @copydoc operator()() */
- template<class... Args>
- decltype(auto) operator()(Args &&...args) {
- return func(*this, std::forward<Args>(args)...);
- }
- private:
- Func func;
- };
- } // namespace entt
- #endif
- // #include "component.hpp"
- // #include "entity.hpp"
- // #include "fwd.hpp"
- // #include "group.hpp"
- #ifndef ENTT_ENTITY_GROUP_HPP
- #define ENTT_ENTITY_GROUP_HPP
- #include <tuple>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- // #include "../core/iterator.hpp"
- // #include "../core/type_traits.hpp"
- // #include "component.hpp"
- // #include "entity.hpp"
- // #include "fwd.hpp"
- // #include "sparse_set.hpp"
- // #include "storage.hpp"
- // #include "utility.hpp"
- namespace entt {
- /**
- * @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, typename>
- class basic_group;
- /**
- * @brief Non-owning group.
- *
- * A non-owning group returns all entities and only the entities that have at
- * least the given components. Moreover, it's guaranteed that the entity list
- * is tightly packed in memory for fast iterations.
- *
- * @b Important
- *
- * Iterators aren't invalidated if:
- *
- * * New instances of the given components are created and assigned to entities.
- * * The entity currently pointed is modified (as an example, if one of the
- * given components is removed from the entity to which the iterator points).
- * * The entity currently pointed is destroyed.
- *
- * In all other cases, modifying the pools iterated by the group in any way
- * invalidates all the iterators and using them results in undefined behavior.
- *
- * @note
- * Groups share references to the underlying data structures of the registry
- * that generated them. Therefore any change to the entities and to the
- * components made by means of the registry are immediately reflected by all the
- * groups.<br/>
- * Moreover, sorting a non-owning group affects all the instances of the same
- * group (it means that users don't have to call `sort` on each instance to sort
- * all of them because they _share_ entities and components).
- *
- * @warning
- * Lifetime of a group must not overcome that of the registry that generated it.
- * In any other case, attempting to use a group results in undefined behavior.
- *
- * @tparam Entity A valid entity type (see entt_traits for more details).
- * @tparam Get Type of components observed by the group.
- * @tparam Exclude Types of components used to filter the group.
- */
- template<typename Entity, typename... Get, typename... Exclude>
- class basic_group<Entity, owned_t<>, get_t<Get...>, exclude_t<Exclude...>> {
- /*! @brief A registry is allowed to create groups. */
- friend class basic_registry<Entity>;
- template<typename Comp>
- using storage_type = constness_as_t<typename storage_traits<Entity, std::remove_const_t<Comp>>::storage_type, Comp>;
- using basic_common_type = std::common_type_t<typename storage_type<Get>::base_type...>;
- struct extended_group_iterator final {
- using difference_type = std::ptrdiff_t;
- using value_type = decltype(std::tuple_cat(std::tuple<Entity>{}, std::declval<basic_group>().get({})));
- using pointer = input_iterator_pointer<value_type>;
- using reference = value_type;
- using iterator_category = std::input_iterator_tag;
- extended_group_iterator() = default;
- extended_group_iterator(typename basic_common_type::iterator from, const std::tuple<storage_type<Get> *...> &args)
- : it{from},
- pools{args} {}
- extended_group_iterator &operator++() ENTT_NOEXCEPT {
- return ++it, *this;
- }
- extended_group_iterator operator++(int) ENTT_NOEXCEPT {
- extended_group_iterator orig = *this;
- return ++(*this), orig;
- }
- [[nodiscard]] reference operator*() const ENTT_NOEXCEPT {
- const auto entt = *it;
- return std::tuple_cat(std::make_tuple(entt), std::get<storage_type<Get> *>(pools)->get_as_tuple(entt)...);
- }
- [[nodiscard]] pointer operator->() const ENTT_NOEXCEPT {
- return operator*();
- }
- [[nodiscard]] bool operator==(const extended_group_iterator &other) const ENTT_NOEXCEPT {
- return other.it == it;
- }
- [[nodiscard]] bool operator!=(const extended_group_iterator &other) const ENTT_NOEXCEPT {
- return !(*this == other);
- }
- private:
- typename basic_common_type::iterator it;
- std::tuple<storage_type<Get> *...> pools;
- };
- basic_group(basic_common_type &ref, storage_type<Get> &...gpool) ENTT_NOEXCEPT
- : handler{&ref},
- pools{&gpool...} {}
- public:
- /*! @brief Underlying entity identifier. */
- using entity_type = Entity;
- /*! @brief Unsigned integer type. */
- using size_type = std::size_t;
- /*! @brief Common type among all storage types. */
- using base_type = basic_common_type;
- /*! @brief Random access iterator type. */
- using iterator = typename base_type::iterator;
- /*! @brief Reversed iterator type. */
- using reverse_iterator = typename base_type::reverse_iterator;
- /*! @brief Iterable group type. */
- using iterable = iterable_adaptor<extended_group_iterator>;
- /*! @brief Default constructor to use to create empty, invalid groups. */
- basic_group() ENTT_NOEXCEPT
- : handler{} {}
- /**
- * @brief Returns a const reference to the underlying handler.
- * @return A const reference to the underlying handler.
- */
- const base_type &handle() const ENTT_NOEXCEPT {
- return *handler;
- }
- /**
- * @brief Returns the storage for a given component type.
- * @tparam Comp Type of component of which to return the storage.
- * @return The storage for the given component type.
- */
- template<typename Comp>
- [[nodiscard]] decltype(auto) storage() const ENTT_NOEXCEPT {
- return *std::get<storage_type<Comp> *>(pools);
- }
- /**
- * @brief Returns the storage for a given component type.
- * @tparam Comp Index of component of which to return the storage.
- * @return The storage for the given component type.
- */
- template<std::size_t Comp>
- [[nodiscard]] decltype(auto) storage() const ENTT_NOEXCEPT {
- return *std::get<Comp>(pools);
- }
- /**
- * @brief Returns the number of entities that have the given components.
- * @return Number of entities that have the given components.
- */
- [[nodiscard]] size_type size() const ENTT_NOEXCEPT {
- return *this ? handler->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 ENTT_NOEXCEPT {
- return *this ? handler->capacity() : size_type{};
- }
- /*! @brief Requests the removal of unused capacity. */
- void shrink_to_fit() {
- if(*this) {
- handler->shrink_to_fit();
- }
- }
- /**
- * @brief Checks whether a group is empty.
- * @return True if the group is empty, false otherwise.
- */
- [[nodiscard]] bool empty() const ENTT_NOEXCEPT {
- return !*this || handler->empty();
- }
- /**
- * @brief Returns an iterator to the first entity of the group.
- *
- * The returned iterator points 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 ENTT_NOEXCEPT {
- return *this ? handler->begin() : iterator{};
- }
- /**
- * @brief Returns an iterator that is past the last entity of the group.
- *
- * The returned iterator points to the entity following the last entity of
- * the group. Attempting to dereference the returned iterator results in
- * undefined behavior.
- *
- * @return An iterator to the entity following the last entity of the
- * group.
- */
- [[nodiscard]] iterator end() const ENTT_NOEXCEPT {
- return *this ? handler->end() : iterator{};
- }
- /**
- * @brief Returns an iterator to the first entity of the reversed group.
- *
- * The returned iterator points 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 ENTT_NOEXCEPT {
- return *this ? handler->rbegin() : reverse_iterator{};
- }
- /**
- * @brief Returns an iterator that is past the last entity of the reversed
- * group.
- *
- * The returned iterator points to the entity following the last entity of
- * the reversed group. Attempting to dereference the returned iterator
- * results in undefined behavior.
- *
- * @return An iterator to the entity following the last entity of the
- * reversed group.
- */
- [[nodiscard]] reverse_iterator rend() const ENTT_NOEXCEPT {
- return *this ? handler->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 ENTT_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 ENTT_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 ENTT_NOEXCEPT {
- const auto it = *this ? handler->find(entt) : iterator{};
- return it != end() && *it == entt ? it : end();
- }
- /**
- * @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()[pos];
- }
- /**
- * @brief Checks if a group is properly initialized.
- * @return True if the group is properly initialized, false otherwise.
- */
- [[nodiscard]] explicit operator bool() const ENTT_NOEXCEPT {
- return handler != 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 ENTT_NOEXCEPT {
- return *this && handler->contains(entt);
- }
- /**
- * @brief Returns the components assigned to the given entity.
- *
- * Prefer this function instead of `registry::get` during iterations. It has
- * far better performance than its counterpart.
- *
- * @warning
- * Attempting to use an invalid component type results in a compilation
- * error. Attempting to use an entity that doesn't belong to the group
- * results in undefined behavior.
- *
- * @tparam Comp Types of components to get.
- * @param entt A valid identifier.
- * @return The components assigned to the entity.
- */
- template<typename... Comp>
- [[nodiscard]] decltype(auto) get(const entity_type entt) const {
- ENTT_ASSERT(contains(entt), "Group does not contain entity");
- if constexpr(sizeof...(Comp) == 0) {
- return std::tuple_cat(std::get<storage_type<Get> *>(pools)->get_as_tuple(entt)...);
- } else if constexpr(sizeof...(Comp) == 1) {
- return (std::get<storage_type<Comp> *>(pools)->get(entt), ...);
- } else {
- return std::tuple_cat(std::get<storage_type<Comp> *>(pools)->get_as_tuple(entt)...);
- }
- }
- /**
- * @brief Iterates entities and components 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 components. The
- * _constness_ of the components 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 components. The _constness_ of the
- * components 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 ENTT_NOEXCEPT {
- return handler ? iterable{extended_group_iterator{handler->begin(), pools}, extended_group_iterator{handler->end(), pools}}
- : iterable{extended_group_iterator{{}, pools}, extended_group_iterator{{}, pools}};
- }
- /**
- * @brief Sort a group according to the given comparison function.
- *
- * Sort the group so that iterating it with a couple of iterators returns
- * entities and components in the expected order. See `begin` and `end` for
- * more details.
- *
- * 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<Component &...>, std::tuple<Component &...>);
- * bool(const Component &..., const Component &...);
- * bool(const Entity, const Entity);
- * @endcode
- *
- * Where `Component` 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 Comp Optional types of components 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... Comp, typename Compare, typename Sort = std_sort, typename... Args>
- void sort(Compare compare, Sort algo = Sort{}, Args &&...args) {
- if(*this) {
- if constexpr(sizeof...(Comp) == 0) {
- static_assert(std::is_invocable_v<Compare, const entity_type, const entity_type>, "Invalid comparison function");
- handler->sort(std::move(compare), std::move(algo), std::forward<Args>(args)...);
- } else {
- auto comp = [this, &compare](const entity_type lhs, const entity_type rhs) {
- if constexpr(sizeof...(Comp) == 1) {
- return compare((std::get<storage_type<Comp> *>(pools)->get(lhs), ...), (std::get<storage_type<Comp> *>(pools)->get(rhs), ...));
- } else {
- return compare(std::forward_as_tuple(std::get<storage_type<Comp> *>(pools)->get(lhs)...), std::forward_as_tuple(std::get<storage_type<Comp> *>(pools)->get(rhs)...));
- }
- };
- handler->sort(std::move(comp), std::move(algo), std::forward<Args>(args)...);
- }
- }
- }
- /**
- * @brief Sort the shared pool of entities according to the given component.
- *
- * Non-owning groups of the same type share with the registry a pool of
- * entities with its own order that doesn't depend on the order of any pool
- * of components. Users can order the underlying data structure so that it
- * respects the order of the pool of the given component.
- *
- * @note
- * The shared pool of entities and thus its order is affected by the changes
- * to each and every pool that it tracks. Therefore changes to those pools
- * can quickly ruin the order imposed to the pool of entities shared between
- * the non-owning groups.
- *
- * @tparam Comp Type of component to use to impose the order.
- */
- template<typename Comp>
- void sort() const {
- if(*this) {
- handler->respect(*std::get<storage_type<Comp> *>(pools));
- }
- }
- private:
- base_type *const handler;
- const std::tuple<storage_type<Get> *...> pools;
- };
- /**
- * @brief Owning group.
- *
- * Owning groups return all entities and only the entities that have at least
- * the given components. Moreover:
- *
- * * It's guaranteed that the entity list is tightly packed in memory for fast
- * iterations.
- * * It's guaranteed that the lists of owned components are tightly packed in
- * memory for even faster iterations and to allow direct access.
- * * They stay true to the order of the owned components and all instances have
- * the same order in memory.
- *
- * The more types of components are owned by a group, the faster it is to
- * iterate them.
- *
- * @b Important
- *
- * Iterators aren't invalidated if:
- *
- * * New instances of the given components are created and assigned to entities.
- * * The entity currently pointed is modified (as an example, if one of the
- * given components is removed from the entity to which the iterator points).
- * * The entity currently pointed is destroyed.
- *
- * In all other cases, modifying the pools iterated by the group in any way
- * invalidates all the iterators and using them results in undefined behavior.
- *
- * @note
- * Groups share references to the underlying data structures of the registry
- * that generated them. Therefore any change to the entities and to the
- * components made by means of the registry are immediately reflected by all the
- * groups.
- * Moreover, sorting an owning group affects all the instance of the same group
- * (it means that users don't have to call `sort` on each instance to sort all
- * of them because they share the underlying data structure).
- *
- * @warning
- * Lifetime of a group must not overcome that of the registry that generated it.
- * In any other case, attempting to use a group results in undefined behavior.
- *
- * @tparam Entity A valid entity type (see entt_traits for more details).
- * @tparam Owned Types of components owned by the group.
- * @tparam Get Types of components observed by the group.
- * @tparam Exclude Types of components used to filter the group.
- */
- template<typename Entity, typename... Owned, typename... Get, typename... Exclude>
- class basic_group<Entity, owned_t<Owned...>, get_t<Get...>, exclude_t<Exclude...>> {
- /*! @brief A registry is allowed to create groups. */
- friend class basic_registry<Entity>;
- template<typename Comp>
- using storage_type = constness_as_t<typename storage_traits<Entity, std::remove_const_t<Comp>>::storage_type, Comp>;
- using basic_common_type = std::common_type_t<typename storage_type<Owned>::base_type..., typename storage_type<Get>::base_type...>;
- class extended_group_iterator final {
- template<typename Type>
- auto index_to_element(storage_type<Type> &cpool) const {
- if constexpr(ignore_as_empty_v<std::remove_const_t<Type>>) {
- return std::make_tuple();
- } else {
- return std::forward_as_tuple(cpool.rbegin()[it.index()]);
- }
- }
- public:
- using difference_type = std::ptrdiff_t;
- using value_type = decltype(std::tuple_cat(std::tuple<Entity>{}, std::declval<basic_group>().get({})));
- using pointer = input_iterator_pointer<value_type>;
- using reference = value_type;
- using iterator_category = std::input_iterator_tag;
- extended_group_iterator() = default;
- template<typename... Other>
- extended_group_iterator(typename basic_common_type::iterator from, const std::tuple<storage_type<Owned> *..., storage_type<Get> *...> &cpools)
- : it{from},
- pools{cpools} {}
- extended_group_iterator &operator++() ENTT_NOEXCEPT {
- return ++it, *this;
- }
- extended_group_iterator operator++(int) ENTT_NOEXCEPT {
- extended_group_iterator orig = *this;
- return ++(*this), orig;
- }
- [[nodiscard]] reference operator*() const ENTT_NOEXCEPT {
- return std::tuple_cat(
- std::make_tuple(*it),
- index_to_element<Owned>(*std::get<storage_type<Owned> *>(pools))...,
- std::get<storage_type<Get> *>(pools)->get_as_tuple(*it)...);
- }
- [[nodiscard]] pointer operator->() const ENTT_NOEXCEPT {
- return operator*();
- }
- [[nodiscard]] bool operator==(const extended_group_iterator &other) const ENTT_NOEXCEPT {
- return other.it == it;
- }
- [[nodiscard]] bool operator!=(const extended_group_iterator &other) const ENTT_NOEXCEPT {
- return !(*this == other);
- }
- private:
- typename basic_common_type::iterator it;
- std::tuple<storage_type<Owned> *..., storage_type<Get> *...> pools;
- };
- basic_group(const std::size_t &extent, storage_type<Owned> &...opool, storage_type<Get> &...gpool) ENTT_NOEXCEPT
- : pools{&opool..., &gpool...},
- length{&extent} {}
- public:
- /*! @brief Underlying entity identifier. */
- using entity_type = Entity;
- /*! @brief Unsigned integer type. */
- using size_type = std::size_t;
- /*! @brief Common type among all storage types. */
- using base_type = basic_common_type;
- /*! @brief Random access iterator type. */
- using iterator = typename base_type::iterator;
- /*! @brief Reversed iterator type. */
- using reverse_iterator = typename base_type::reverse_iterator;
- /*! @brief Iterable group type. */
- using iterable = iterable_adaptor<extended_group_iterator>;
- /*! @brief Default constructor to use to create empty, invalid groups. */
- basic_group() ENTT_NOEXCEPT
- : length{} {}
- /**
- * @brief Returns the storage for a given component type.
- * @tparam Comp Type of component of which to return the storage.
- * @return The storage for the given component type.
- */
- template<typename Comp>
- [[nodiscard]] decltype(auto) storage() const ENTT_NOEXCEPT {
- return *std::get<storage_type<Comp> *>(pools);
- }
- /**
- * @brief Returns the storage for a given component type.
- * @tparam Comp Index of component of which to return the storage.
- * @return The storage for the given component type.
- */
- template<std::size_t Comp>
- [[nodiscard]] decltype(auto) storage() const ENTT_NOEXCEPT {
- return *std::get<Comp>(pools);
- }
- /**
- * @brief Returns the number of entities that have the given components.
- * @return Number of entities that have the given components.
- */
- [[nodiscard]] size_type size() const ENTT_NOEXCEPT {
- return *this ? *length : size_type{};
- }
- /**
- * @brief Checks whether a group is empty.
- * @return True if the group is empty, false otherwise.
- */
- [[nodiscard]] bool empty() const ENTT_NOEXCEPT {
- return !*this || !*length;
- }
- /**
- * @brief Returns an iterator to the first entity of the group.
- *
- * The returned iterator points 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 ENTT_NOEXCEPT {
- return *this ? (std::get<0>(pools)->base_type::end() - *length) : iterator{};
- }
- /**
- * @brief Returns an iterator that is past the last entity of the group.
- *
- * The returned iterator points to the entity following the last entity of
- * the group. Attempting to dereference the returned iterator results in
- * undefined behavior.
- *
- * @return An iterator to the entity following the last entity of the
- * group.
- */
- [[nodiscard]] iterator end() const ENTT_NOEXCEPT {
- return *this ? std::get<0>(pools)->base_type::end() : iterator{};
- }
- /**
- * @brief Returns an iterator to the first entity of the reversed group.
- *
- * The returned iterator points 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 ENTT_NOEXCEPT {
- return *this ? std::get<0>(pools)->base_type::rbegin() : reverse_iterator{};
- }
- /**
- * @brief Returns an iterator that is past the last entity of the reversed
- * group.
- *
- * The returned iterator points to the entity following the last entity of
- * the reversed group. Attempting to dereference the returned iterator
- * results in undefined behavior.
- *
- * @return An iterator to the entity following the last entity of the
- * reversed group.
- */
- [[nodiscard]] reverse_iterator rend() const ENTT_NOEXCEPT {
- return *this ? (std::get<0>(pools)->base_type::rbegin() + *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 ENTT_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 ENTT_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 ENTT_NOEXCEPT {
- const auto it = *this ? std::get<0>(pools)->find(entt) : iterator{};
- return it != end() && it >= begin() && *it == entt ? it : end();
- }
- /**
- * @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()[pos];
- }
- /**
- * @brief Checks if a group is properly initialized.
- * @return True if the group is properly initialized, false otherwise.
- */
- [[nodiscard]] explicit operator bool() const ENTT_NOEXCEPT {
- return length != 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 ENTT_NOEXCEPT {
- return *this && std::get<0>(pools)->contains(entt) && (std::get<0>(pools)->index(entt) < (*length));
- }
- /**
- * @brief Returns the components assigned to the given entity.
- *
- * Prefer this function instead of `registry::get` during iterations. It has
- * far better performance than its counterpart.
- *
- * @warning
- * Attempting to use an invalid component type results in a compilation
- * error. Attempting to use an entity that doesn't belong to the group
- * results in undefined behavior.
- *
- * @tparam Comp Types of components to get.
- * @param entt A valid identifier.
- * @return The components assigned to the entity.
- */
- template<typename... Comp>
- [[nodiscard]] decltype(auto) get(const entity_type entt) const {
- ENTT_ASSERT(contains(entt), "Group does not contain entity");
- if constexpr(sizeof...(Comp) == 0) {
- return std::tuple_cat(std::get<storage_type<Owned> *>(pools)->get_as_tuple(entt)..., std::get<storage_type<Get> *>(pools)->get_as_tuple(entt)...);
- } else if constexpr(sizeof...(Comp) == 1) {
- return (std::get<storage_type<Comp> *>(pools)->get(entt), ...);
- } else {
- return std::tuple_cat(std::get<storage_type<Comp> *>(pools)->get_as_tuple(entt)...);
- }
- }
- /**
- * @brief Iterates entities and components 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 components. The
- * _constness_ of the components 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 components. The _constness_ of the
- * components 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 ENTT_NOEXCEPT {
- iterator last = length ? std::get<0>(pools)->basic_common_type::end() : iterator{};
- return {extended_group_iterator{last - *length, pools}, extended_group_iterator{last, pools}};
- }
- /**
- * @brief Sort a group according to the given comparison function.
- *
- * Sort the group so that iterating it with a couple of iterators returns
- * entities and components in the expected order. See `begin` and `end` for
- * more details.
- *
- * 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<Component &...>, std::tuple<Component &...>);
- * bool(const Component &, const Component &);
- * bool(const Entity, const Entity);
- * @endcode
- *
- * Where `Component` 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 Comp Optional types of components 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... Comp, typename Compare, typename Sort = std_sort, typename... Args>
- void sort(Compare compare, Sort algo = Sort{}, Args &&...args) const {
- auto *cpool = std::get<0>(pools);
- if constexpr(sizeof...(Comp) == 0) {
- static_assert(std::is_invocable_v<Compare, const entity_type, const entity_type>, "Invalid comparison function");
- cpool->sort_n(*length, std::move(compare), std::move(algo), std::forward<Args>(args)...);
- } else {
- auto comp = [this, &compare](const entity_type lhs, const entity_type rhs) {
- if constexpr(sizeof...(Comp) == 1) {
- return compare((std::get<storage_type<Comp> *>(pools)->get(lhs), ...), (std::get<storage_type<Comp> *>(pools)->get(rhs), ...));
- } else {
- return compare(std::forward_as_tuple(std::get<storage_type<Comp> *>(pools)->get(lhs)...), std::forward_as_tuple(std::get<storage_type<Comp> *>(pools)->get(rhs)...));
- }
- };
- cpool->sort_n(*length, std::move(comp), std::move(algo), std::forward<Args>(args)...);
- }
- [this](auto *head, auto *...other) {
- for(auto next = *length; next; --next) {
- const auto pos = next - 1;
- [[maybe_unused]] const auto entt = head->data()[pos];
- (other->swap_elements(other->data()[pos], entt), ...);
- }
- }(std::get<storage_type<Owned> *>(pools)...);
- }
- private:
- const std::tuple<storage_type<Owned> *..., storage_type<Get> *...> pools;
- const size_type *const length;
- };
- } // namespace entt
- #endif
- // #include "runtime_view.hpp"
- #ifndef ENTT_ENTITY_RUNTIME_VIEW_HPP
- #define ENTT_ENTITY_RUNTIME_VIEW_HPP
- #include <algorithm>
- #include <iterator>
- #include <type_traits>
- #include <utility>
- #include <vector>
- // #include "../config/config.h"
- // #include "entity.hpp"
- // #include "fwd.hpp"
- // #include "sparse_set.hpp"
- namespace entt {
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- namespace internal {
- template<typename Set>
- class runtime_view_iterator final {
- using iterator_type = typename Set::iterator;
- [[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 difference_type = typename iterator_type::difference_type;
- using value_type = typename iterator_type::value_type;
- using pointer = typename iterator_type::pointer;
- using reference = typename iterator_type::reference;
- using iterator_category = std::bidirectional_iterator_tag;
- runtime_view_iterator() ENTT_NOEXCEPT
- : pools{},
- filter{},
- it{},
- tombstone_check{} {}
- runtime_view_iterator(const std::vector<const Set *> &cpools, const std::vector<const Set *> &ignore, iterator_type curr) ENTT_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++() {
- while(++it != (*pools)[0]->end() && !valid()) {}
- return *this;
- }
- runtime_view_iterator operator++(int) {
- runtime_view_iterator orig = *this;
- return ++(*this), orig;
- }
- runtime_view_iterator &operator--() {
- while(--it != (*pools)[0]->begin() && !valid()) {}
- return *this;
- }
- runtime_view_iterator operator--(int) {
- runtime_view_iterator orig = *this;
- return operator--(), orig;
- }
- [[nodiscard]] pointer operator->() const ENTT_NOEXCEPT {
- return it.operator->();
- }
- [[nodiscard]] reference operator*() const ENTT_NOEXCEPT {
- return *operator->();
- }
- [[nodiscard]] bool operator==(const runtime_view_iterator &other) const ENTT_NOEXCEPT {
- return it == other.it;
- }
- [[nodiscard]] bool operator!=(const runtime_view_iterator &other) const ENTT_NOEXCEPT {
- return !(*this == other);
- }
- private:
- const std::vector<const Set *> *pools;
- const std::vector<const Set *> *filter;
- iterator_type it;
- bool tombstone_check;
- };
- } // namespace internal
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /**
- * @brief Runtime view implementation.
- *
- * Primary template isn't defined on purpose. All the specializations give a
- * compile-time error, but for a few reasonable cases.
- */
- template<typename>
- struct basic_runtime_view;
- /**
- * @brief Generic runtime view.
- *
- * Runtime views iterate over those entities that have at least all the given
- * components in their bags. During initialization, a runtime view looks at the
- * number of entities available for each component and picks up a reference to
- * the smallest set of candidate entities in order to get a performance boost
- * when iterate.<br/>
- * Order of elements during iterations are highly dependent on the order of the
- * underlying data structures. See sparse_set and its specializations for more
- * details.
- *
- * @b Important
- *
- * Iterators aren't invalidated if:
- *
- * * New instances of the given components are created and assigned to entities.
- * * The entity currently pointed is modified (as an example, if one of the
- * given components is removed from the entity to which the iterator points).
- * * The entity currently pointed is destroyed.
- *
- * In all the other cases, modifying the pools of the given components in any
- * way invalidates all the iterators and using them results in undefined
- * behavior.
- *
- * @note
- * Views share references to the underlying data structures of the registry that
- * generated them. Therefore any change to the entities and to the components
- * made by means of the registry are immediately reflected by the views, unless
- * a pool was missing when the view was built (in this case, the view won't
- * have a valid reference and won't be updated accordingly).
- *
- * @warning
- * Lifetime of a view must not overcome that of the registry that generated it.
- * In any other case, attempting to use a view results in undefined behavior.
- *
- * @tparam Entity A valid entity type (see entt_traits for more details).
- * @tparam Allocator Type of allocator used to manage memory and elements.
- */
- template<typename Entity, typename Allocator>
- struct basic_runtime_view<basic_sparse_set<Entity, Allocator>> {
- /*! @brief Underlying entity identifier. */
- using entity_type = Entity;
- /*! @brief Unsigned integer type. */
- using size_type = std::size_t;
- /*! @brief Common type among all storage types. */
- using base_type = basic_sparse_set<Entity, Allocator>;
- /*! @brief Bidirectional iterator type. */
- using iterator = internal::runtime_view_iterator<base_type>;
- /*! @brief Default constructor to use to create empty, invalid views. */
- basic_runtime_view() ENTT_NOEXCEPT
- : pools{},
- filter{} {}
- /**
- * @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(const base_type &base) {
- if(pools.empty() || !(base.size() < pools[0u]->size())) {
- pools.push_back(&base);
- } else {
- pools.push_back(std::exchange(pools[0u], &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(const base_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{} : pools.front()->size();
- }
- /**
- * @brief Returns an iterator to the first entity that has the given
- * components.
- *
- * The returned iterator points to the first entity that has the given
- * components. If the view is empty, the returned iterator will be equal to
- * `end()`.
- *
- * @return An iterator to the first entity that has the given components.
- */
- [[nodiscard]] iterator begin() const {
- return pools.empty() ? iterator{} : iterator{pools, filter, pools[0]->begin()};
- }
- /**
- * @brief Returns an iterator that is past the last entity that has the
- * given components.
- *
- * The returned iterator points to the entity following the last entity that
- * has the given components. Attempting to dereference the returned iterator
- * results in undefined behavior.
- *
- * @return An iterator to the entity following the last entity that has the
- * given components.
- */
- [[nodiscard]] iterator end() const {
- return pools.empty() ? iterator{} : iterator{pools, filter, pools[0]->end()};
- }
- /**
- * @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); });
- }
- /**
- * @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. To get the components, users can use the registry with
- * which the view was built.<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:
- std::vector<const base_type *> pools;
- std::vector<const base_type *> filter;
- };
- } // namespace entt
- #endif
- // #include "sparse_set.hpp"
- // #include "storage.hpp"
- // #include "utility.hpp"
- // #include "view.hpp"
- #ifndef ENTT_ENTITY_VIEW_HPP
- #define ENTT_ENTITY_VIEW_HPP
- #include <algorithm>
- #include <array>
- #include <iterator>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- // #include "../core/iterator.hpp"
- // #include "../core/type_traits.hpp"
- // #include "component.hpp"
- // #include "entity.hpp"
- // #include "fwd.hpp"
- // #include "sparse_set.hpp"
- // #include "storage.hpp"
- // #include "utility.hpp"
- namespace entt {
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- namespace internal {
- template<typename Type, std::size_t Component, std::size_t Exclude>
- class view_iterator final {
- using iterator_type = typename Type::const_iterator;
- [[nodiscard]] bool valid() const ENTT_NOEXCEPT {
- return ((Component != 0u) || (*it != tombstone))
- && std::apply([entt = *it](const auto *...curr) { return (curr->contains(entt) && ...); }, pools)
- && std::apply([entt = *it](const auto *...curr) { return (!curr->contains(entt) && ...); }, filter);
- }
- public:
- using value_type = typename iterator_type::value_type;
- using pointer = typename iterator_type::pointer;
- using reference = typename iterator_type::reference;
- using difference_type = typename iterator_type::difference_type;
- using iterator_category = std::forward_iterator_tag;
- view_iterator() ENTT_NOEXCEPT = default;
- view_iterator(iterator_type curr, iterator_type to, std::array<const Type *, Component> all_of, std::array<const Type *, Exclude> none_of) ENTT_NOEXCEPT
- : it{curr},
- last{to},
- pools{all_of},
- filter{none_of} {
- if(it != last && !valid()) {
- ++(*this);
- }
- }
- view_iterator &operator++() ENTT_NOEXCEPT {
- while(++it != last && !valid()) {}
- return *this;
- }
- view_iterator operator++(int) ENTT_NOEXCEPT {
- view_iterator orig = *this;
- return ++(*this), orig;
- }
- [[nodiscard]] pointer operator->() const ENTT_NOEXCEPT {
- return &*it;
- }
- [[nodiscard]] reference operator*() const ENTT_NOEXCEPT {
- return *operator->();
- }
- template<typename LhsType, auto... LhsArgs, typename RhsType, auto... RhsArgs>
- friend bool operator==(const view_iterator<LhsType, LhsArgs...> &, const view_iterator<RhsType, RhsArgs...> &) ENTT_NOEXCEPT;
- private:
- iterator_type it;
- iterator_type last;
- std::array<const Type *, Component> pools;
- std::array<const Type *, Exclude> filter;
- };
- template<typename LhsType, auto... LhsArgs, typename RhsType, auto... RhsArgs>
- [[nodiscard]] bool operator==(const view_iterator<LhsType, LhsArgs...> &lhs, const view_iterator<RhsType, RhsArgs...> &rhs) ENTT_NOEXCEPT {
- return lhs.it == rhs.it;
- }
- template<typename LhsType, auto... LhsArgs, typename RhsType, auto... RhsArgs>
- [[nodiscard]] bool operator!=(const view_iterator<LhsType, LhsArgs...> &lhs, const view_iterator<RhsType, RhsArgs...> &rhs) ENTT_NOEXCEPT {
- return !(lhs == rhs);
- }
- template<typename It, typename... Storage>
- struct extended_view_iterator final {
- using difference_type = std::ptrdiff_t;
- using value_type = decltype(std::tuple_cat(std::make_tuple(*std::declval<It>()), std::declval<Storage>().get_as_tuple({})...));
- using pointer = input_iterator_pointer<value_type>;
- using reference = value_type;
- using iterator_category = std::input_iterator_tag;
- extended_view_iterator() = default;
- extended_view_iterator(It from, std::tuple<Storage *...> storage)
- : it{from},
- pools{storage} {}
- extended_view_iterator &operator++() ENTT_NOEXCEPT {
- return ++it, *this;
- }
- extended_view_iterator operator++(int) ENTT_NOEXCEPT {
- extended_view_iterator orig = *this;
- return ++(*this), orig;
- }
- [[nodiscard]] reference operator*() const ENTT_NOEXCEPT {
- return std::apply([entt = *it](auto *...curr) { return std::tuple_cat(std::make_tuple(entt), curr->get_as_tuple(entt)...); }, pools);
- }
- [[nodiscard]] pointer operator->() const ENTT_NOEXCEPT {
- return operator*();
- }
- template<typename... Lhs, typename... Rhs>
- friend bool operator==(const extended_view_iterator<Lhs...> &, const extended_view_iterator<Rhs...> &) ENTT_NOEXCEPT;
- private:
- It it;
- std::tuple<Storage *...> pools;
- };
- template<typename... Lhs, typename... Rhs>
- [[nodiscard]] bool operator==(const extended_view_iterator<Lhs...> &lhs, const extended_view_iterator<Rhs...> &rhs) ENTT_NOEXCEPT {
- return lhs.it == rhs.it;
- }
- template<typename... Lhs, typename... Rhs>
- [[nodiscard]] bool operator!=(const extended_view_iterator<Lhs...> &lhs, const extended_view_iterator<Rhs...> &rhs) ENTT_NOEXCEPT {
- return !(lhs == rhs);
- }
- } // namespace internal
- /**
- * Internal details not to be documented.
- * @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.
- */
- template<typename, typename, typename, typename>
- class basic_view;
- /**
- * @brief Multi component view.
- *
- * Multi component views iterate over those entities that have at least all the
- * given components in their bags. During initialization, a multi component view
- * looks at the number of entities available for each component and uses the
- * smallest set in order to get a performance boost when iterate.
- *
- * @b Important
- *
- * Iterators aren't invalidated if:
- *
- * * New instances of the given components are created and assigned to entities.
- * * The entity currently pointed is modified (as an example, if one of the
- * given components is removed from the entity to which the iterator points).
- * * The entity currently pointed is destroyed.
- *
- * In all other cases, modifying the pools iterated by the view in any way
- * invalidates all the iterators and using them results in undefined behavior.
- *
- * @tparam Entity A valid entity type (see entt_traits for more details).
- * @tparam Component Types of components iterated by the view.
- * @tparam Exclude Types of components used to filter the view.
- */
- template<typename Entity, typename... Component, typename... Exclude>
- class basic_view<Entity, get_t<Component...>, exclude_t<Exclude...>> {
- template<typename, typename, typename, typename>
- friend class basic_view;
- template<typename Comp>
- using storage_type = constness_as_t<typename storage_traits<Entity, std::remove_const_t<Comp>>::storage_type, Comp>;
- template<std::size_t... Index>
- [[nodiscard]] auto pools_to_array(std::index_sequence<Index...>) const ENTT_NOEXCEPT {
- std::size_t pos{};
- std::array<const base_type *, sizeof...(Component) - 1u> other{};
- (static_cast<void>(std::get<Index>(pools) == view ? void() : void(other[pos++] = std::get<Index>(pools))), ...);
- return other;
- }
- template<std::size_t Comp, std::size_t Other, typename... Args>
- [[nodiscard]] auto dispatch_get(const std::tuple<Entity, Args...> &curr) const {
- if constexpr(Comp == Other) {
- return std::forward_as_tuple(std::get<Args>(curr)...);
- } else {
- return std::get<Other>(pools)->get_as_tuple(std::get<0>(curr));
- }
- }
- template<std::size_t Comp, typename Func, std::size_t... Index>
- void each(Func func, std::index_sequence<Index...>) const {
- for(const auto curr: std::get<Comp>(pools)->each()) {
- const auto entt = std::get<0>(curr);
- if(((sizeof...(Component) != 1u) || (entt != tombstone))
- && ((Comp == Index || std::get<Index>(pools)->contains(entt)) && ...)
- && std::apply([entt](const auto *...cpool) { return (!cpool->contains(entt) && ...); }, filter)) {
- 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<Comp, Index>(curr)...));
- } else {
- std::apply(func, std::tuple_cat(dispatch_get<Comp, Index>(curr)...));
- }
- }
- }
- }
- template<typename Func, std::size_t... Index>
- void pick_and_each(Func func, std::index_sequence<Index...> seq) const {
- ((std::get<Index>(pools) == view ? each<Index>(std::move(func), seq) : void()), ...);
- }
- public:
- /*! @brief Underlying entity identifier. */
- using entity_type = Entity;
- /*! @brief Unsigned integer type. */
- using size_type = std::size_t;
- /*! @brief Common type among all storage types. */
- using base_type = std::common_type_t<typename storage_type<Component>::base_type...>;
- /*! @brief Bidirectional iterator type. */
- using iterator = internal::view_iterator<base_type, sizeof...(Component) - 1u, sizeof...(Exclude)>;
- /*! @brief Iterable view type. */
- using iterable = iterable_adaptor<internal::extended_view_iterator<iterator, storage_type<Component>...>>;
- /*! @brief Default constructor to use to create empty, invalid views. */
- basic_view() ENTT_NOEXCEPT
- : pools{},
- filter{},
- view{} {}
- /**
- * @brief Constructs a multi-type view from a set of storage classes.
- * @param component The storage for the types to iterate.
- * @param epool The storage for the types used to filter the view.
- */
- basic_view(storage_type<Component> &...component, const storage_type<Exclude> &...epool) ENTT_NOEXCEPT
- : pools{&component...},
- filter{&epool...},
- view{(std::min)({&static_cast<const base_type &>(component)...}, [](auto *lhs, auto *rhs) { return lhs->size() < rhs->size(); })} {}
- /**
- * @brief Creates a new view driven by a given component in its iterations.
- * @tparam Comp Type of component used to drive the iteration.
- * @return A new view driven by the given component in its iterations.
- */
- template<typename Comp>
- [[nodiscard]] basic_view use() const ENTT_NOEXCEPT {
- basic_view other{*this};
- other.view = std::get<storage_type<Comp> *>(pools);
- return other;
- }
- /**
- * @brief Creates a new view driven by a given component in its iterations.
- * @tparam Comp Index of the component used to drive the iteration.
- * @return A new view driven by the given component in its iterations.
- */
- template<std::size_t Comp>
- [[nodiscard]] basic_view use() const ENTT_NOEXCEPT {
- basic_view other{*this};
- other.view = std::get<Comp>(pools);
- return other;
- }
- /**
- * @brief Returns the leading storage of a view.
- * @return The leading storage of the view.
- */
- const base_type &handle() const ENTT_NOEXCEPT {
- return *view;
- }
- /**
- * @brief Returns the storage for a given component type.
- * @tparam Comp Type of component of which to return the storage.
- * @return The storage for the given component type.
- */
- template<typename Comp>
- [[nodiscard]] decltype(auto) storage() const ENTT_NOEXCEPT {
- return *std::get<storage_type<Comp> *>(pools);
- }
- /**
- * @brief Returns the storage for a given component type.
- * @tparam Comp Index of component of which to return the storage.
- * @return The storage for the given component type.
- */
- template<std::size_t Comp>
- [[nodiscard]] decltype(auto) storage() const ENTT_NOEXCEPT {
- return *std::get<Comp>(pools);
- }
- /**
- * @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 ENTT_NOEXCEPT {
- return view->size();
- }
- /**
- * @brief Returns an iterator to the first entity of the view.
- *
- * The returned iterator points 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 ENTT_NOEXCEPT {
- return iterator{view->begin(), view->end(), pools_to_array(std::index_sequence_for<Component...>{}), filter};
- }
- /**
- * @brief Returns an iterator that is past the last entity of the view.
- *
- * The returned iterator points to the entity following the last entity of
- * the view. Attempting to dereference the returned iterator results in
- * undefined behavior.
- *
- * @return An iterator to the entity following the last entity of the view.
- */
- [[nodiscard]] iterator end() const ENTT_NOEXCEPT {
- return iterator{view->end(), view->end(), pools_to_array(std::index_sequence_for<Component...>{}), filter};
- }
- /**
- * @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 ENTT_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 ENTT_NOEXCEPT {
- auto it = view->rbegin();
- for(const auto last = view->rend(); it != last && !contains(*it); ++it) {}
- return it == view->rend() ? null : *it;
- }
- /**
- * @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 ENTT_NOEXCEPT {
- return contains(entt) ? iterator{view->find(entt), view->end(), pools_to_array(std::index_sequence_for<Component...>{}), filter} : end();
- }
- /**
- * @brief Returns the components assigned to the given entity.
- * @param entt A valid identifier.
- * @return The components assigned to the given entity.
- */
- [[nodiscard]] decltype(auto) operator[](const entity_type entt) const {
- return get<Component...>(entt);
- }
- /**
- * @brief Checks if a view is properly initialized.
- * @return True if the view is properly initialized, false otherwise.
- */
- [[nodiscard]] explicit operator bool() const ENTT_NOEXCEPT {
- return view != 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 ENTT_NOEXCEPT {
- return std::apply([entt](const auto *...curr) { return (curr->contains(entt) && ...); }, pools)
- && std::apply([entt](const auto *...curr) { return (!curr->contains(entt) && ...); }, filter);
- }
- /**
- * @brief Returns the components assigned to the given entity.
- *
- * @warning
- * Attempting to use an entity that doesn't belong to the view results in
- * undefined behavior.
- *
- * @tparam Comp Types of components to get.
- * @param entt A valid identifier.
- * @return The components assigned to the entity.
- */
- template<typename... Comp>
- [[nodiscard]] decltype(auto) get(const entity_type entt) const {
- ENTT_ASSERT(contains(entt), "View does not contain entity");
- if constexpr(sizeof...(Comp) == 0) {
- return std::apply([entt](auto *...curr) { return std::tuple_cat(curr->get_as_tuple(entt)...); }, pools);
- } else if constexpr(sizeof...(Comp) == 1) {
- return (std::get<storage_type<Comp> *>(pools)->get(entt), ...);
- } else {
- return std::tuple_cat(std::get<storage_type<Comp> *>(pools)->get_as_tuple(entt)...);
- }
- }
- /**
- * @brief Returns the components assigned to the given entity.
- *
- * @warning
- * Attempting to use an entity that doesn't belong to the view results in
- * undefined behavior.
- *
- * @tparam First Index of a component to get.
- * @tparam Other Indexes of other components to get.
- * @param entt A valid identifier.
- * @return The components assigned to the entity.
- */
- template<std::size_t First, std::size_t... Other>
- [[nodiscard]] decltype(auto) get(const entity_type entt) const {
- ENTT_ASSERT(contains(entt), "View does not contain entity");
- if constexpr(sizeof...(Other) == 0) {
- return std::get<First>(pools)->get(entt);
- } else {
- return std::tuple_cat(std::get<First>(pools)->get_as_tuple(entt), std::get<Other>(pools)->get_as_tuple(entt)...);
- }
- }
- /**
- * @brief Iterates entities and components 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 components. The
- * _constness_ of the components 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
- *
- * @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(std::move(func), std::index_sequence_for<Component...>{});
- }
- /**
- * @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 components. The _constness_ of the
- * components is as requested.
- *
- * @return An iterable object to use to _visit_ the view.
- */
- [[nodiscard]] iterable each() const ENTT_NOEXCEPT {
- return {internal::extended_view_iterator{begin(), pools}, internal::extended_view_iterator{end(), pools}};
- }
- /**
- * @brief Combines two views in a _more specific_ one (friend function).
- * @tparam Get Component list of the view to combine with.
- * @tparam Excl Filter list of the view to combine with.
- * @param other The view to combine with.
- * @return A more specific view.
- */
- template<typename... Get, typename... Excl>
- [[nodiscard]] auto operator|(const basic_view<Entity, get_t<Get...>, exclude_t<Excl...>> &other) const ENTT_NOEXCEPT {
- using view_type = basic_view<Entity, get_t<Component..., Get...>, exclude_t<Exclude..., Excl...>>;
- return std::make_from_tuple<view_type>(std::tuple_cat(
- std::apply([](auto *...curr) { return std::forward_as_tuple(*curr...); }, pools),
- std::apply([](auto *...curr) { return std::forward_as_tuple(*curr...); }, other.pools),
- std::apply([](const auto *...curr) { return std::forward_as_tuple(static_cast<const storage_type<Exclude> &>(*curr)...); }, filter),
- std::apply([](const auto *...curr) { return std::forward_as_tuple(static_cast<const storage_type<Excl> &>(*curr)...); }, other.filter)));
- }
- private:
- std::tuple<storage_type<Component> *...> pools;
- std::array<const base_type *, sizeof...(Exclude)> filter;
- const base_type *view;
- };
- /**
- * @brief Single component view specialization.
- *
- * Single component views are specialized in order to get a boost in terms of
- * performance. This kind of views can access the underlying data structure
- * directly and avoid superfluous checks.
- *
- * @b Important
- *
- * Iterators aren't invalidated if:
- *
- * * New instances of the given component are created and assigned to entities.
- * * The entity currently pointed is modified (as an example, the given
- * component is removed from the entity to which the iterator points).
- * * The entity currently pointed is destroyed.
- *
- * In all other cases, modifying the pool iterated by the view in any way
- * invalidates all the iterators and using them results in undefined behavior.
- *
- * @tparam Entity A valid entity type (see entt_traits for more details).
- * @tparam Component Type of component iterated by the view.
- */
- template<typename Entity, typename Component>
- class basic_view<Entity, get_t<Component>, exclude_t<>, std::void_t<std::enable_if_t<!component_traits<std::remove_const_t<Component>>::in_place_delete>>> {
- template<typename, typename, typename, typename>
- friend class basic_view;
- using storage_type = constness_as_t<typename storage_traits<Entity, std::remove_const_t<Component>>::storage_type, Component>;
- public:
- /*! @brief Underlying entity identifier. */
- using entity_type = Entity;
- /*! @brief Unsigned integer type. */
- using size_type = std::size_t;
- /*! @brief Common type among all storage types. */
- using base_type = typename storage_type::base_type;
- /*! @brief Random access iterator type. */
- using iterator = typename base_type::iterator;
- /*! @brief Reversed iterator type. */
- using reverse_iterator = typename base_type::reverse_iterator;
- /*! @brief Iterable view type. */
- using iterable = decltype(std::declval<storage_type>().each());
- /*! @brief Default constructor to use to create empty, invalid views. */
- basic_view() ENTT_NOEXCEPT
- : pools{},
- filter{},
- view{} {}
- /**
- * @brief Constructs a single-type view from a storage class.
- * @param ref The storage for the type to iterate.
- */
- basic_view(storage_type &ref) ENTT_NOEXCEPT
- : pools{&ref},
- filter{},
- view{&ref} {}
- /**
- * @brief Returns the leading storage of a view.
- * @return The leading storage of the view.
- */
- const base_type &handle() const ENTT_NOEXCEPT {
- return *view;
- }
- /**
- * @brief Returns the storage for a given component type.
- * @tparam Comp Type of component of which to return the storage.
- * @return The storage for the given component type.
- */
- template<typename Comp = Component>
- [[nodiscard]] decltype(auto) storage() const ENTT_NOEXCEPT {
- static_assert(std::is_same_v<Comp, Component>, "Invalid component type");
- return *std::get<0>(pools);
- }
- /**
- * @brief Returns the storage for a given component type.
- * @tparam Comp Index of component of which to return the storage.
- * @return The storage for the given component type.
- */
- template<std::size_t Comp>
- [[nodiscard]] decltype(auto) storage() const ENTT_NOEXCEPT {
- return *std::get<Comp>(pools);
- }
- /**
- * @brief Returns the number of entities that have the given component.
- * @return Number of entities that have the given component.
- */
- [[nodiscard]] size_type size() const ENTT_NOEXCEPT {
- return view->size();
- }
- /**
- * @brief Checks whether a view is empty.
- * @return True if the view is empty, false otherwise.
- */
- [[nodiscard]] bool empty() const ENTT_NOEXCEPT {
- return view->empty();
- }
- /**
- * @brief Returns an iterator to the first entity of the view.
- *
- * The returned iterator points 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 ENTT_NOEXCEPT {
- return view->begin();
- }
- /**
- * @brief Returns an iterator that is past the last entity of the view.
- *
- * The returned iterator points to the entity following the last entity of
- * the view. Attempting to dereference the returned iterator results in
- * undefined behavior.
- *
- * @return An iterator to the entity following the last entity of the view.
- */
- [[nodiscard]] iterator end() const ENTT_NOEXCEPT {
- return view->end();
- }
- /**
- * @brief Returns an iterator to the first entity of the reversed view.
- *
- * The returned iterator points to the first entity of the reversed view. If
- * the view is empty, the returned iterator will be equal to `rend()`.
- *
- * @return An iterator to the first entity of the reversed view.
- */
- [[nodiscard]] reverse_iterator rbegin() const ENTT_NOEXCEPT {
- return view->rbegin();
- }
- /**
- * @brief Returns an iterator that is past the last entity of the reversed
- * view.
- *
- * The returned iterator points to the entity following the last entity of
- * the reversed view. Attempting to dereference the returned iterator
- * results in undefined behavior.
- *
- * @return An iterator to the entity following the last entity of the
- * reversed view.
- */
- [[nodiscard]] reverse_iterator rend() const ENTT_NOEXCEPT {
- return view->rend();
- }
- /**
- * @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 ENTT_NOEXCEPT {
- return empty() ? null : *begin();
- }
- /**
- * @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 ENTT_NOEXCEPT {
- return empty() ? null : *rbegin();
- }
- /**
- * @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 ENTT_NOEXCEPT {
- return contains(entt) ? view->find(entt) : end();
- }
- /**
- * @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()[pos];
- }
- /**
- * @brief Returns the component assigned to the given entity.
- * @param entt A valid identifier.
- * @return The component assigned to the given entity.
- */
- [[nodiscard]] decltype(auto) operator[](const entity_type entt) const {
- return get<Component>(entt);
- }
- /**
- * @brief Checks if a view is properly initialized.
- * @return True if the view is properly initialized, false otherwise.
- */
- [[nodiscard]] explicit operator bool() const ENTT_NOEXCEPT {
- return view != 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 ENTT_NOEXCEPT {
- return view->contains(entt);
- }
- /**
- * @brief Returns the component assigned to the given entity.
- *
- * @warning
- * Attempting to use an entity that doesn't belong to the view results in
- * undefined behavior.
- *
- * @tparam Comp Type or index of the component to get.
- * @param entt A valid identifier.
- * @return The component assigned to the entity.
- */
- template<typename... Comp>
- [[nodiscard]] decltype(auto) get(const entity_type entt) const {
- ENTT_ASSERT(contains(entt), "View does not contain entity");
- if constexpr(sizeof...(Comp) == 0) {
- return std::get<0>(pools)->get_as_tuple(entt);
- } else {
- static_assert(std::is_same_v<Comp..., Component>, "Invalid component type");
- return std::get<0>(pools)->get(entt);
- }
- }
- /*! @copydoc get */
- template<std::size_t Comp>
- [[nodiscard]] decltype(auto) get(const entity_type entt) const {
- ENTT_ASSERT(contains(entt), "View does not contain entity");
- return std::get<0>(pools)->get(entt);
- }
- /**
- * @brief Iterates entities and components 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 reference to the component if it's a non-empty one.
- * The _constness_ of the component is as requested.<br/>
- * The signature of the function must be equivalent to one of the following
- * forms:
- *
- * @code{.cpp}
- * void(const entity_type, Component &);
- * void(Component &);
- * @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(*each().begin())>) {
- for(const auto pack: each()) {
- std::apply(func, pack);
- }
- } else if constexpr(std::is_invocable_v<Func, Component &>) {
- for(auto &&component: *std::get<0>(pools)) {
- func(component);
- }
- } else if constexpr(std::is_invocable_v<Func, Entity>) {
- for(auto entity: *view) {
- func(entity);
- }
- } else {
- for(size_type pos{}, last = size(); pos < last; ++pos) {
- func();
- }
- }
- }
- /**
- * @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 component if it's a non-empty one. The _constness_ of
- * the component is as requested.
- *
- * @return An iterable object to use to _visit_ the view.
- */
- [[nodiscard]] iterable each() const ENTT_NOEXCEPT {
- return std::get<0>(pools)->each();
- }
- /**
- * @brief Combines two views in a _more specific_ one (friend function).
- * @tparam Get Component list of the view to combine with.
- * @tparam Excl Filter list of the view to combine with.
- * @param other The view to combine with.
- * @return A more specific view.
- */
- template<typename... Get, typename... Excl>
- [[nodiscard]] auto operator|(const basic_view<Entity, get_t<Get...>, exclude_t<Excl...>> &other) const ENTT_NOEXCEPT {
- using view_type = basic_view<Entity, get_t<Component, Get...>, exclude_t<Excl...>>;
- return std::make_from_tuple<view_type>(std::tuple_cat(
- std::forward_as_tuple(*std::get<0>(pools)),
- std::apply([](auto *...curr) { return std::forward_as_tuple(*curr...); }, other.pools),
- std::apply([](const auto *...curr) { return std::forward_as_tuple(static_cast<const typename view_type::template storage_type<Excl> &>(*curr)...); }, other.filter)));
- }
- private:
- std::tuple<storage_type *> pools;
- std::array<const base_type *, 0u> filter;
- const base_type *view;
- };
- /**
- * @brief Deduction guide.
- * @tparam Storage Type of storage classes used to create the view.
- * @param storage The storage for the types to iterate.
- */
- template<typename... Storage>
- basic_view(Storage &...storage) -> basic_view<std::common_type_t<typename Storage::entity_type...>, get_t<constness_as_t<typename Storage::value_type, Storage>...>, exclude_t<>>;
- } // namespace entt
- #endif
- namespace entt {
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- namespace internal {
- template<typename It>
- class storage_proxy_iterator final {
- template<typename Other>
- friend class storage_proxy_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;
- storage_proxy_iterator() ENTT_NOEXCEPT
- : it{} {}
- storage_proxy_iterator(const It iter) ENTT_NOEXCEPT
- : it{iter} {}
- template<typename Other, typename = std::enable_if_t<!std::is_same_v<It, Other> && std::is_constructible_v<It, Other>>>
- storage_proxy_iterator(const storage_proxy_iterator<Other> &other) ENTT_NOEXCEPT
- : it{other.it} {}
- storage_proxy_iterator &operator++() ENTT_NOEXCEPT {
- return ++it, *this;
- }
- storage_proxy_iterator operator++(int) ENTT_NOEXCEPT {
- storage_proxy_iterator orig = *this;
- return ++(*this), orig;
- }
- storage_proxy_iterator &operator--() ENTT_NOEXCEPT {
- return --it, *this;
- }
- storage_proxy_iterator operator--(int) ENTT_NOEXCEPT {
- storage_proxy_iterator orig = *this;
- return operator--(), orig;
- }
- storage_proxy_iterator &operator+=(const difference_type value) ENTT_NOEXCEPT {
- it += value;
- return *this;
- }
- storage_proxy_iterator operator+(const difference_type value) const ENTT_NOEXCEPT {
- storage_proxy_iterator copy = *this;
- return (copy += value);
- }
- storage_proxy_iterator &operator-=(const difference_type value) ENTT_NOEXCEPT {
- return (*this += -value);
- }
- storage_proxy_iterator operator-(const difference_type value) const ENTT_NOEXCEPT {
- return (*this + -value);
- }
- [[nodiscard]] reference operator[](const difference_type value) const ENTT_NOEXCEPT {
- return {it[value].first, *it[value].second};
- }
- [[nodiscard]] reference operator*() const ENTT_NOEXCEPT {
- return {it->first, *it->second};
- }
- [[nodiscard]] pointer operator->() const ENTT_NOEXCEPT {
- return operator*();
- }
- template<typename ILhs, typename IRhs>
- friend std::ptrdiff_t operator-(const storage_proxy_iterator<ILhs> &, const storage_proxy_iterator<IRhs> &) ENTT_NOEXCEPT;
- template<typename ILhs, typename IRhs>
- friend bool operator==(const storage_proxy_iterator<ILhs> &, const storage_proxy_iterator<IRhs> &) ENTT_NOEXCEPT;
- template<typename ILhs, typename IRhs>
- friend bool operator<(const storage_proxy_iterator<ILhs> &, const storage_proxy_iterator<IRhs> &) ENTT_NOEXCEPT;
- private:
- It it;
- };
- template<typename ILhs, typename IRhs>
- [[nodiscard]] std::ptrdiff_t operator-(const storage_proxy_iterator<ILhs> &lhs, const storage_proxy_iterator<IRhs> &rhs) ENTT_NOEXCEPT {
- return lhs.it - rhs.it;
- }
- template<typename ILhs, typename IRhs>
- [[nodiscard]] bool operator==(const storage_proxy_iterator<ILhs> &lhs, const storage_proxy_iterator<IRhs> &rhs) ENTT_NOEXCEPT {
- return lhs.it == rhs.it;
- }
- template<typename ILhs, typename IRhs>
- [[nodiscard]] bool operator!=(const storage_proxy_iterator<ILhs> &lhs, const storage_proxy_iterator<IRhs> &rhs) ENTT_NOEXCEPT {
- return !(lhs == rhs);
- }
- template<typename ILhs, typename IRhs>
- [[nodiscard]] bool operator<(const storage_proxy_iterator<ILhs> &lhs, const storage_proxy_iterator<IRhs> &rhs) ENTT_NOEXCEPT {
- return lhs.it < rhs.it;
- }
- template<typename ILhs, typename IRhs>
- [[nodiscard]] bool operator>(const storage_proxy_iterator<ILhs> &lhs, const storage_proxy_iterator<IRhs> &rhs) ENTT_NOEXCEPT {
- return rhs < lhs;
- }
- template<typename ILhs, typename IRhs>
- [[nodiscard]] bool operator<=(const storage_proxy_iterator<ILhs> &lhs, const storage_proxy_iterator<IRhs> &rhs) ENTT_NOEXCEPT {
- return !(lhs > rhs);
- }
- template<typename ILhs, typename IRhs>
- [[nodiscard]] bool operator>=(const storage_proxy_iterator<ILhs> &lhs, const storage_proxy_iterator<IRhs> &rhs) ENTT_NOEXCEPT {
- return !(lhs < rhs);
- }
- struct registry_context {
- template<typename Type, typename... Args>
- Type &emplace_hint(const id_type id, Args &&...args) {
- return any_cast<Type &>(data.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_hint<Type>(type_id<Type>().hash(), std::forward<Args>(args)...);
- }
- template<typename Type>
- bool erase(const id_type id = type_id<Type>().hash()) {
- const auto it = data.find(id);
- return it != data.end() && it->second.type() == type_id<Type>() ? (data.erase(it), true) : false;
- }
- template<typename Type>
- [[nodiscard]] std::add_const_t<Type> &at(const id_type id = type_id<Type>().hash()) const {
- return any_cast<std::add_const_t<Type> &>(data.at(id));
- }
- template<typename Type>
- [[nodiscard]] Type &at(const id_type id = type_id<Type>().hash()) {
- return any_cast<Type &>(data.at(id));
- }
- template<typename Type>
- [[nodiscard]] std::add_const_t<Type> *find(const id_type id = type_id<Type>().hash()) const {
- const auto it = data.find(id);
- return it != data.cend() ? any_cast<std::add_const_t<Type>>(&it->second) : nullptr;
- }
- template<typename Type>
- [[nodiscard]] Type *find(const id_type id = type_id<Type>().hash()) {
- const auto it = data.find(id);
- return it != data.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 = data.find(id);
- return it != data.end() && it->second.type() == type_id<Type>();
- }
- private:
- dense_map<id_type, basic_any<0u>, identity> data;
- };
- } // namespace internal
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /**
- * @brief Fast and reliable entity-component system.
- * @tparam Entity A valid entity type (see entt_traits for more details).
- */
- template<typename Entity>
- class basic_registry {
- using entity_traits = entt_traits<Entity>;
- using basic_common_type = basic_sparse_set<Entity>;
- template<typename Component>
- using storage_type = typename storage_traits<Entity, Component>::storage_type;
- template<typename...>
- struct group_handler;
- template<typename... Exclude, typename... Get, typename... Owned>
- struct group_handler<exclude_t<Exclude...>, get_t<Get...>, Owned...> {
- // nasty workaround for an issue with the toolset v141 that doesn't accept a fold expression here
- static_assert(!std::disjunction_v<std::bool_constant<component_traits<Owned>::in_place_delete>...>, "Groups do not support in-place delete");
- std::conditional_t<sizeof...(Owned) == 0, basic_common_type, std::size_t> current{};
- template<typename Component>
- void maybe_valid_if(basic_registry &owner, const Entity entt) {
- [[maybe_unused]] const auto cpools = std::forward_as_tuple(owner.assure<Owned>()...);
- const auto is_valid = ((std::is_same_v<Component, Owned> || std::get<storage_type<Owned> &>(cpools).contains(entt)) && ...)
- && ((std::is_same_v<Component, Get> || owner.assure<Get>().contains(entt)) && ...)
- && ((std::is_same_v<Component, Exclude> || !owner.assure<Exclude>().contains(entt)) && ...);
- if constexpr(sizeof...(Owned) == 0) {
- if(is_valid && !current.contains(entt)) {
- current.emplace(entt);
- }
- } else {
- if(is_valid && !(std::get<0>(cpools).index(entt) < current)) {
- const auto pos = current++;
- (std::get<storage_type<Owned> &>(cpools).swap_elements(std::get<storage_type<Owned> &>(cpools).data()[pos], entt), ...);
- }
- }
- }
- void discard_if([[maybe_unused]] basic_registry &owner, const Entity entt) {
- if constexpr(sizeof...(Owned) == 0) {
- current.remove(entt);
- } else {
- if(const auto cpools = std::forward_as_tuple(owner.assure<Owned>()...); std::get<0>(cpools).contains(entt) && (std::get<0>(cpools).index(entt) < current)) {
- const auto pos = --current;
- (std::get<storage_type<Owned> &>(cpools).swap_elements(std::get<storage_type<Owned> &>(cpools).data()[pos], entt), ...);
- }
- }
- }
- };
- struct group_data {
- std::size_t size;
- std::unique_ptr<void, void (*)(void *)> group;
- bool (*owned)(const id_type) ENTT_NOEXCEPT;
- bool (*get)(const id_type) ENTT_NOEXCEPT;
- bool (*exclude)(const id_type) ENTT_NOEXCEPT;
- };
- template<typename Component>
- [[nodiscard]] auto &assure(const id_type id = type_hash<Component>::value()) {
- static_assert(std::is_same_v<Component, std::decay_t<Component>>, "Non-decayed types not allowed");
- auto &&cpool = pools[id];
- if(!cpool) {
- cpool.reset(new storage_type<Component>{});
- cpool->bind(forward_as_any(*this));
- }
- ENTT_ASSERT(cpool->type() == type_id<Component>(), "Unexpected type");
- return static_cast<storage_type<Component> &>(*cpool);
- }
- template<typename Component>
- [[nodiscard]] const auto &assure(const id_type id = type_hash<Component>::value()) const {
- static_assert(std::is_same_v<Component, std::decay_t<Component>>, "Non-decayed types not allowed");
- if(const auto it = pools.find(id); it != pools.cend()) {
- ENTT_ASSERT(it->second->type() == type_id<Component>(), "Unexpected type");
- return static_cast<const storage_type<Component> &>(*it->second);
- }
- static storage_type<Component> placeholder{};
- return placeholder;
- }
- auto generate_identifier(const std::size_t pos) ENTT_NOEXCEPT {
- ENTT_ASSERT(pos < entity_traits::to_entity(null), "No entities available");
- return entity_traits::combine(static_cast<typename entity_traits::entity_type>(pos), {});
- }
- auto recycle_identifier() ENTT_NOEXCEPT {
- ENTT_ASSERT(free_list != null, "No entities available");
- const auto curr = entity_traits::to_entity(free_list);
- free_list = entity_traits::combine(entity_traits::to_integral(entities[curr]), tombstone);
- return (entities[curr] = entity_traits::combine(curr, entity_traits::to_integral(entities[curr])));
- }
- auto release_entity(const Entity entity, const typename entity_traits::version_type version) {
- const typename entity_traits::version_type vers = version + (version == entity_traits::to_version(tombstone));
- entities[entity_traits::to_entity(entity)] = entity_traits::construct(entity_traits::to_integral(free_list), vers);
- free_list = entity_traits::combine(entity_traits::to_integral(entity), tombstone);
- return vers;
- }
- public:
- /*! @brief Underlying entity identifier. */
- using entity_type = Entity;
- /*! @brief Underlying version type. */
- using version_type = typename entity_traits::version_type;
- /*! @brief Unsigned integer type. */
- using size_type = std::size_t;
- /*! @brief Common type among all storage types. */
- using base_type = basic_common_type;
- /*! @brief Context type. */
- using context = internal::registry_context;
- /*! @brief Default constructor. */
- basic_registry()
- : pools{},
- groups{},
- entities{},
- free_list{tombstone},
- vars{} {}
- /**
- * @brief Allocates enough memory upon construction to store `count` pools.
- * @param count The number of pools to allocate memory for.
- */
- basic_registry(const size_type count)
- : pools{},
- groups{},
- entities{},
- free_list{tombstone},
- vars{} {
- pools.reserve(count);
- }
- /**
- * @brief Move constructor.
- * @param other The instance to move from.
- */
- basic_registry(basic_registry &&other)
- : pools{std::move(other.pools)},
- groups{std::move(other.groups)},
- entities{std::move(other.entities)},
- free_list{other.free_list},
- vars{std::move(other.vars)} {
- for(auto &&curr: pools) {
- curr.second->bind(forward_as_any(*this));
- }
- }
- /**
- * @brief Move assignment operator.
- * @param other The instance to move from.
- * @return This registry.
- */
- basic_registry &operator=(basic_registry &&other) {
- pools = std::move(other.pools);
- groups = std::move(other.groups);
- entities = std::move(other.entities);
- free_list = other.free_list;
- vars = std::move(other.vars);
- for(auto &&curr: pools) {
- curr.second->bind(forward_as_any(*this));
- }
- return *this;
- }
- /**
- * @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]] auto storage() ENTT_NOEXCEPT {
- return iterable_adaptor{internal::storage_proxy_iterator{pools.begin()}, internal::storage_proxy_iterator{pools.end()}};
- }
- /*! @copydoc storage */
- [[nodiscard]] auto storage() const ENTT_NOEXCEPT {
- return iterable_adaptor{internal::storage_proxy_iterator{pools.cbegin()}, internal::storage_proxy_iterator{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 An iterator to the given storage if it's found, past the end
- * iterator otherwise.
- */
- [[nodiscard]] auto storage(const id_type id) {
- return internal::storage_proxy_iterator{pools.find(id)};
- }
- /**
- * @brief Finds the storage associated with a given name, if any.
- * @param id Name used to map the storage within the registry.
- * @return An iterator to the given storage if it's found, past the end
- * iterator otherwise.
- */
- [[nodiscard]] auto storage(const id_type id) const {
- return internal::storage_proxy_iterator{pools.find(id)};
- }
- /**
- * @brief Returns the storage for a given component type.
- * @tparam Component Type of component of which to return the storage.
- * @param id Optional name used to map the storage within the registry.
- * @return The storage for the given component type.
- */
- template<typename Component>
- decltype(auto) storage(const id_type id = type_hash<std::remove_const_t<Component>>::value()) {
- if constexpr(std::is_const_v<Component>) {
- return std::as_const(*this).template storage<std::remove_const_t<Component>>(id);
- } else {
- return assure<Component>(id);
- }
- }
- /**
- * @brief Returns the storage for a given component type.
- *
- * @warning
- * If a storage for the given component doesn't exist yet, a temporary
- * placeholder is returned instead.
- *
- * @tparam Component Type of component of which to return the storage.
- * @param id Optional name used to map the storage within the registry.
- * @return The storage for the given component type.
- */
- template<typename Component>
- decltype(auto) storage(const id_type id = type_hash<std::remove_const_t<Component>>::value()) const {
- return assure<std::remove_const_t<Component>>(id);
- }
- /**
- * @brief Returns the number of entities created so far.
- * @return Number of entities created so far.
- */
- [[nodiscard]] size_type size() const ENTT_NOEXCEPT {
- return entities.size();
- }
- /**
- * @brief Returns the number of entities still in use.
- * @return Number of entities still in use.
- */
- [[nodiscard]] size_type alive() const {
- auto sz = entities.size();
- for(auto curr = free_list; curr != null; --sz) {
- curr = entities[entity_traits::to_entity(curr)];
- }
- return sz;
- }
- /**
- * @brief Increases the capacity (number of entities) of the registry.
- * @param cap Desired capacity.
- */
- void reserve(const size_type cap) {
- entities.reserve(cap);
- }
- /**
- * @brief Returns the number of entities that a registry has currently
- * allocated space for.
- * @return Capacity of the registry.
- */
- [[nodiscard]] size_type capacity() const ENTT_NOEXCEPT {
- return entities.capacity();
- }
- /**
- * @brief Checks whether the registry is empty (no entities still in use).
- * @return True if the registry is empty, false otherwise.
- */
- [[nodiscard]] bool empty() const {
- return !alive();
- }
- /**
- * @brief Direct access to the list of entities of a registry.
- *
- * The returned pointer is such that range `[data(), data() + size())` is
- * always a valid range, even if the registry is empty.
- *
- * @warning
- * This list contains both valid and destroyed entities and isn't suitable
- * for direct use.
- *
- * @return A pointer to the array of entities.
- */
- [[nodiscard]] const entity_type *data() const ENTT_NOEXCEPT {
- return entities.data();
- }
- /**
- * @brief Returns the head of the list of released entities.
- *
- * This function is intended for use in conjunction with `assign`.<br/>
- * The returned entity has an invalid identifier in all cases.
- *
- * @return The head of the list of released entities.
- */
- [[nodiscard]] entity_type released() const ENTT_NOEXCEPT {
- return free_list;
- }
- /**
- * @brief Checks if an identifier refers to a valid entity.
- * @param entity An identifier, either valid or not.
- * @return True if the identifier is valid, false otherwise.
- */
- [[nodiscard]] bool valid(const entity_type entity) const {
- const auto pos = size_type(entity_traits::to_entity(entity));
- return (pos < entities.size() && entities[pos] == entity);
- }
- /**
- * @brief Returns the actual version for an identifier.
- * @param entity A valid identifier.
- * @return The version for the given identifier if valid, the tombstone
- * version otherwise.
- */
- [[nodiscard]] version_type current(const entity_type entity) const {
- const auto pos = size_type(entity_traits::to_entity(entity));
- return entity_traits::to_version(pos < entities.size() ? entities[pos] : tombstone);
- }
- /**
- * @brief Creates a new entity or recycles a destroyed one.
- * @return A valid identifier.
- */
- [[nodiscard]] entity_type create() {
- return (free_list == null) ? entities.emplace_back(generate_identifier(entities.size())) : recycle_identifier();
- }
- /**
- * @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) {
- const auto length = entities.size();
- if(hint == null || hint == tombstone) {
- return create();
- } else if(const auto req = entity_traits::to_entity(hint); !(req < length)) {
- entities.resize(size_type(req) + 1u, null);
- for(auto pos = length; pos < req; ++pos) {
- release_entity(generate_identifier(pos), {});
- }
- return (entities[req] = hint);
- } else if(const auto curr = entity_traits::to_entity(entities[req]); req == curr) {
- return create();
- } else {
- auto *it = &free_list;
- for(; entity_traits::to_entity(*it) != req; it = &entities[entity_traits::to_entity(*it)]) {}
- *it = entity_traits::combine(curr, entity_traits::to_integral(*it));
- return (entities[req] = 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) {
- for(; free_list != null && first != last; ++first) {
- *first = recycle_identifier();
- }
- const auto length = entities.size();
- entities.resize(length + std::distance(first, last), null);
- for(auto pos = length; first != last; ++first, ++pos) {
- *first = entities[pos] = generate_identifier(pos);
- }
- }
- /**
- * @brief Assigns identifiers to an empty registry.
- *
- * This function is intended for use in conjunction with `data`, `size` and
- * `destroyed`.<br/>
- * Don't try to inject ranges of randomly generated entities nor the _wrong_
- * head for the list of destroyed entities. There is no guarantee that a
- * registry will continue to work properly in this case.
- *
- * @warning
- * There must be no entities still alive for this to work properly.
- *
- * @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 destroyed The head of the list of destroyed entities.
- */
- template<typename It>
- void assign(It first, It last, const entity_type destroyed) {
- ENTT_ASSERT(!alive(), "Entities still alive");
- entities.assign(first, last);
- free_list = destroyed;
- }
- /**
- * @brief Releases an identifier.
- *
- * The version is updated and the identifier can be recycled at any time.
- *
- * @warning
- * Attempting to use an invalid entity results in undefined behavior.
- *
- * @param entity A valid identifier.
- * @return The version of the recycled entity.
- */
- version_type release(const entity_type entity) {
- return release(entity, static_cast<version_type>(entity_traits::to_version(entity) + 1u));
- }
- /**
- * @brief Releases an identifier.
- *
- * The suggested version or the valid version closest to the suggested one
- * is used instead of the implicitly generated version.
- *
- * @sa release
- *
- * @param entity A valid identifier.
- * @param version A desired version upon destruction.
- * @return The version actually assigned to the entity.
- */
- version_type release(const entity_type entity, const version_type version) {
- ENTT_ASSERT(orphan(entity), "Non-orphan entity");
- return release_entity(entity, version);
- }
- /**
- * @brief Releases all identifiers in a range.
- *
- * @sa release
- *
- * @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 release(It first, It last) {
- for(; first != last; ++first) {
- release(*first);
- }
- }
- /**
- * @brief Destroys an entity and releases its identifier.
- *
- * @sa release
- *
- * @warning
- * Adding or removing components to an entity that is being destroyed can
- * result in undefined behavior. Attempting to use an invalid entity results
- * in undefined behavior.
- *
- * @param entity A valid identifier.
- * @return The version of the recycled entity.
- */
- version_type destroy(const entity_type entity) {
- return destroy(entity, static_cast<version_type>(entity_traits::to_version(entity) + 1u));
- }
- /**
- * @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 entity A valid identifier.
- * @param version A desired version upon destruction.
- * @return The version actually assigned to the entity.
- */
- version_type destroy(const entity_type entity, const version_type version) {
- ENTT_ASSERT(valid(entity), "Invalid entity");
- for(size_type pos = pools.size(); pos; --pos) {
- pools.begin()[pos - 1u].second->remove(entity);
- }
- return release_entity(entity, version);
- }
- /**
- * @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) {
- for(; first != last; ++first) {
- destroy(*first);
- }
- }
- /**
- * @brief Assigns the given component to an entity.
- *
- * The component must have a proper constructor or be of aggregate type.
- *
- * @warning
- * Attempting to use an invalid entity or to assign a component to an entity
- * that already owns it results in undefined behavior.
- *
- * @tparam Component Type of component to create.
- * @tparam Args Types of arguments to use to construct the component.
- * @param entity A valid identifier.
- * @param args Parameters to use to initialize the component.
- * @return A reference to the newly created component.
- */
- template<typename Component, typename... Args>
- decltype(auto) emplace(const entity_type entity, Args &&...args) {
- ENTT_ASSERT(valid(entity), "Invalid entity");
- return assure<Component>().emplace(entity, std::forward<Args>(args)...);
- }
- /**
- * @brief Assigns each entity in a range the given component.
- *
- * @sa emplace
- *
- * @tparam Component Type of component 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 component to assign.
- */
- template<typename Component, typename It>
- void insert(It first, It last, const Component &value = {}) {
- ENTT_ASSERT(std::all_of(first, last, [this](const auto entity) { return valid(entity); }), "Invalid entity");
- assure<Component>().insert(first, last, value);
- }
- /**
- * @brief Assigns each entity in a range the given components.
- *
- * @sa emplace
- *
- * @tparam Component Type of component 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 components.
- */
- template<typename Component, typename EIt, typename CIt, typename = std::enable_if_t<std::is_same_v<typename std::iterator_traits<CIt>::value_type, Component>>>
- void insert(EIt first, EIt last, CIt from) {
- ENTT_ASSERT(std::all_of(first, last, [this](const auto entity) { return valid(entity); }), "Invalid entity");
- assure<Component>().insert(first, last, from);
- }
- /**
- * @brief Assigns or replaces the given component for an entity.
- *
- * @warning
- * Attempting to use an invalid entity results in undefined behavior.
- *
- * @tparam Component Type of component to assign or replace.
- * @tparam Args Types of arguments to use to construct the component.
- * @param entity A valid identifier.
- * @param args Parameters to use to initialize the component.
- * @return A reference to the newly created component.
- */
- template<typename Component, typename... Args>
- decltype(auto) emplace_or_replace(const entity_type entity, Args &&...args) {
- ENTT_ASSERT(valid(entity), "Invalid entity");
- auto &cpool = assure<Component>();
- return cpool.contains(entity)
- ? cpool.patch(entity, [&args...](auto &...curr) { ((curr = Component{std::forward<Args>(args)...}), ...); })
- : cpool.emplace(entity, std::forward<Args>(args)...);
- }
- /**
- * @brief Patches the given component for an entity.
- *
- * The signature of the function should be equivalent to the following:
- *
- * @code{.cpp}
- * void(Component &);
- * @endcode
- *
- * @note
- * Empty types aren't explicitly instantiated and therefore they are never
- * returned. However, this function can be used to trigger an update signal
- * for them.
- *
- * @warning
- * Attempting to use an invalid entity or to patch a component of an entity
- * that doesn't own it results in undefined behavior.
- *
- * @tparam Component Type of component to patch.
- * @tparam Func Types of the function objects to invoke.
- * @param entity A valid identifier.
- * @param func Valid function objects.
- * @return A reference to the patched component.
- */
- template<typename Component, typename... Func>
- decltype(auto) patch(const entity_type entity, Func &&...func) {
- ENTT_ASSERT(valid(entity), "Invalid entity");
- return assure<Component>().patch(entity, std::forward<Func>(func)...);
- }
- /**
- * @brief Replaces the given component for an entity.
- *
- * The component must have a proper constructor or be of aggregate type.
- *
- * @warning
- * Attempting to use an invalid entity or to replace a component of an
- * entity that doesn't own it results in undefined behavior.
- *
- * @tparam Component Type of component to replace.
- * @tparam Args Types of arguments to use to construct the component.
- * @param entity A valid identifier.
- * @param args Parameters to use to initialize the component.
- * @return A reference to the component being replaced.
- */
- template<typename Component, typename... Args>
- decltype(auto) replace(const entity_type entity, Args &&...args) {
- ENTT_ASSERT(valid(entity), "Invalid entity");
- return assure<Component>().patch(entity, [&args...](auto &...curr) { ((curr = Component{std::forward<Args>(args)...}), ...); });
- }
- /**
- * @brief Removes the given components from an entity.
- *
- * @warning
- * Attempting to use an invalid entity results in undefined behavior.
- *
- * @tparam Component Type of component to remove.
- * @tparam Other Other types of components to remove.
- * @param entity A valid identifier.
- * @return The number of components actually removed.
- */
- template<typename Component, typename... Other>
- size_type remove(const entity_type entity) {
- ENTT_ASSERT(valid(entity), "Invalid entity");
- return (assure<Component>().remove(entity) + ... + assure<Other>().remove(entity));
- }
- /**
- * @brief Removes the given components from all the entities in a range.
- *
- * @sa remove
- *
- * @tparam Component Type of component to remove.
- * @tparam Other Other types of components 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 components actually removed.
- */
- template<typename Component, typename... Other, typename It>
- size_type remove(It first, It last) {
- if constexpr(sizeof...(Other) == 0u) {
- ENTT_ASSERT(std::all_of(first, last, [this](const auto entity) { return valid(entity); }), "Invalid entity");
- return assure<Component>().remove(std::move(first), std::move(last));
- } else {
- size_type count{};
- for(auto cpools = std::forward_as_tuple(assure<Component>(), assure<Other>()...); first != last; ++first) {
- ENTT_ASSERT(valid(*first), "Invalid entity");
- count += std::apply([entt = *first](auto &...curr) { return (curr.remove(entt) + ... + 0u); }, cpools);
- }
- return count;
- }
- }
- /**
- * @brief Erases the given components from an entity.
- *
- * @warning
- * Attempting to use an invalid entity or to erase a component from an
- * entity that doesn't own it results in undefined behavior.
- *
- * @tparam Component Types of components to erase.
- * @tparam Other Other types of components to erase.
- * @param entity A valid identifier.
- */
- template<typename Component, typename... Other>
- void erase(const entity_type entity) {
- ENTT_ASSERT(valid(entity), "Invalid entity");
- (assure<Component>().erase(entity), (assure<Other>().erase(entity), ...));
- }
- /**
- * @brief Erases the given components from all the entities in a range.
- *
- * @sa erase
- *
- * @tparam Component Types of components to erase.
- * @tparam Other Other types of components 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 Component, typename... Other, typename It>
- void erase(It first, It last) {
- if constexpr(sizeof...(Other) == 0u) {
- ENTT_ASSERT(std::all_of(first, last, [this](const auto entity) { return valid(entity); }), "Invalid entity");
- assure<Component>().erase(std::move(first), std::move(last));
- } else {
- for(auto cpools = std::forward_as_tuple(assure<Component>(), assure<Other>()...); first != last; ++first) {
- ENTT_ASSERT(valid(*first), "Invalid entity");
- std::apply([entt = *first](auto &...curr) { (curr.erase(entt), ...); }, cpools);
- }
- }
- }
- /**
- * @brief Removes all tombstones from a registry or only the pools for the
- * given components.
- * @tparam Component Types of components for which to clear all tombstones.
- */
- template<typename... Component>
- void compact() {
- if constexpr(sizeof...(Component) == 0) {
- for(auto &&curr: pools) {
- curr.second->compact();
- }
- } else {
- (assure<Component>().compact(), ...);
- }
- }
- /**
- * @brief Checks if an entity has all the given components.
- *
- * @warning
- * Attempting to use an invalid entity results in undefined behavior.
- *
- * @tparam Component Components for which to perform the check.
- * @param entity A valid identifier.
- * @return True if the entity has all the components, false otherwise.
- */
- template<typename... Component>
- [[nodiscard]] bool all_of(const entity_type entity) const {
- ENTT_ASSERT(valid(entity), "Invalid entity");
- return (assure<std::remove_const_t<Component>>().contains(entity) && ...);
- }
- /**
- * @brief Checks if an entity has at least one of the given components.
- *
- * @warning
- * Attempting to use an invalid entity results in undefined behavior.
- *
- * @tparam Component Components for which to perform the check.
- * @param entity A valid identifier.
- * @return True if the entity has at least one of the given components,
- * false otherwise.
- */
- template<typename... Component>
- [[nodiscard]] bool any_of(const entity_type entity) const {
- ENTT_ASSERT(valid(entity), "Invalid entity");
- return (assure<std::remove_const_t<Component>>().contains(entity) || ...);
- }
- /**
- * @brief Returns references to the given components for an entity.
- *
- * @warning
- * Attempting to use an invalid entity or to get a component from an entity
- * that doesn't own it results in undefined behavior.
- *
- * @tparam Component Types of components to get.
- * @param entity A valid identifier.
- * @return References to the components owned by the entity.
- */
- template<typename... Component>
- [[nodiscard]] decltype(auto) get([[maybe_unused]] const entity_type entity) const {
- ENTT_ASSERT(valid(entity), "Invalid entity");
- return view<Component...>().template get<const Component...>(entity);
- }
- /*! @copydoc get */
- template<typename... Component>
- [[nodiscard]] decltype(auto) get([[maybe_unused]] const entity_type entity) {
- ENTT_ASSERT(valid(entity), "Invalid entity");
- return view<Component...>().template get<Component...>(entity);
- }
- /**
- * @brief Returns a reference to the given component for an entity.
- *
- * In case the entity doesn't own the component, the parameters provided are
- * used to construct it.
- *
- * @warning
- * Attempting to use an invalid entity results in undefined behavior.
- *
- * @tparam Component Type of component to get.
- * @tparam Args Types of arguments to use to construct the component.
- * @param entity A valid identifier.
- * @param args Parameters to use to initialize the component.
- * @return Reference to the component owned by the entity.
- */
- template<typename Component, typename... Args>
- [[nodiscard]] decltype(auto) get_or_emplace(const entity_type entity, Args &&...args) {
- ENTT_ASSERT(valid(entity), "Invalid entity");
- auto &cpool = assure<Component>();
- return cpool.contains(entity) ? cpool.get(entity) : cpool.emplace(entity, std::forward<Args>(args)...);
- }
- /**
- * @brief Returns pointers to the given components for an entity.
- *
- * @warning
- * Attempting to use an invalid entity results in undefined behavior.
- *
- * @note
- * The registry retains ownership of the pointed-to components.
- *
- * @tparam Component Types of components to get.
- * @param entity A valid identifier.
- * @return Pointers to the components owned by the entity.
- */
- template<typename... Component>
- [[nodiscard]] auto try_get([[maybe_unused]] const entity_type entity) const {
- ENTT_ASSERT(valid(entity), "Invalid entity");
- if constexpr(sizeof...(Component) == 1) {
- const auto &cpool = assure<std::remove_const_t<Component>...>();
- return cpool.contains(entity) ? std::addressof(cpool.get(entity)) : nullptr;
- } else {
- return std::make_tuple(try_get<Component>(entity)...);
- }
- }
- /*! @copydoc try_get */
- template<typename... Component>
- [[nodiscard]] auto try_get([[maybe_unused]] const entity_type entity) {
- if constexpr(sizeof...(Component) == 1) {
- return (const_cast<Component *>(std::as_const(*this).template try_get<Component>(entity)), ...);
- } else {
- return std::make_tuple(try_get<Component>(entity)...);
- }
- }
- /**
- * @brief Clears a whole registry or the pools for the given components.
- * @tparam Component Types of components to remove from their entities.
- */
- template<typename... Component>
- void clear() {
- if constexpr(sizeof...(Component) == 0) {
- for(auto &&curr: pools) {
- curr.second->clear();
- }
- each([this](const auto entity) { this->release(entity); });
- } else {
- (assure<Component>().clear(), ...);
- }
- }
- /**
- * @brief Iterates all the entities that are still in use.
- *
- * The signature of the function should be equivalent to the following:
- *
- * @code{.cpp}
- * void(const Entity);
- * @endcode
- *
- * It's not defined whether entities created during iteration are returned.
- *
- * @tparam Func Type of the function object to invoke.
- * @param func A valid function object.
- */
- template<typename Func>
- void each(Func func) const {
- if(free_list == null) {
- for(auto pos = entities.size(); pos; --pos) {
- func(entities[pos - 1]);
- }
- } else {
- for(auto pos = entities.size(); pos; --pos) {
- if(const auto entity = entities[pos - 1]; entity_traits::to_entity(entity) == (pos - 1)) {
- func(entity);
- }
- }
- }
- }
- /**
- * @brief Checks if an entity has components assigned.
- * @param entity A valid identifier.
- * @return True if the entity has no components assigned, false otherwise.
- */
- [[nodiscard]] bool orphan(const entity_type entity) const {
- ENTT_ASSERT(valid(entity), "Invalid entity");
- return std::none_of(pools.cbegin(), pools.cend(), [entity](auto &&curr) { return curr.second->contains(entity); });
- }
- /**
- * @brief Returns a sink object for the given component.
- *
- * Use this function to receive notifications whenever a new instance of the
- * given component 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 component to the entity.
- *
- * @sa sink
- *
- * @tparam Component Type of component of which to get the sink.
- * @return A temporary sink object.
- */
- template<typename Component>
- [[nodiscard]] auto on_construct() {
- return assure<Component>().on_construct();
- }
- /**
- * @brief Returns a sink object for the given component.
- *
- * Use this function to receive notifications whenever an instance of the
- * given component 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 component.
- *
- * @sa sink
- *
- * @tparam Component Type of component of which to get the sink.
- * @return A temporary sink object.
- */
- template<typename Component>
- [[nodiscard]] auto on_update() {
- return assure<Component>().on_update();
- }
- /**
- * @brief Returns a sink object for the given component.
- *
- * Use this function to receive notifications whenever an instance of the
- * given component 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 component from the entity.
- *
- * @sa sink
- *
- * @tparam Component Type of component of which to get the sink.
- * @return A temporary sink object.
- */
- template<typename Component>
- [[nodiscard]] auto on_destroy() {
- return assure<Component>().on_destroy();
- }
- /**
- * @brief Returns a view for the given components.
- *
- * Views are created on the fly and share with the registry its internal
- * data structures. Feel free to discard them after the use.<br/>
- * Creating and destroying a view is an incredibly cheap operation. As a
- * rule of thumb, storing a view should never be an option.
- *
- * @tparam Component Type of component used to construct the view.
- * @tparam Other Other types of components used to construct the view.
- * @tparam Exclude Types of components used to filter the view.
- * @return A newly created view.
- */
- template<typename Component, typename... Other, typename... Exclude>
- [[nodiscard]] basic_view<entity_type, get_t<std::add_const_t<Component>, std::add_const_t<Other>...>, exclude_t<Exclude...>> view(exclude_t<Exclude...> = {}) const {
- return {assure<std::remove_const_t<Component>>(), assure<std::remove_const_t<Other>>()..., assure<Exclude>()...};
- }
- /*! @copydoc view */
- template<typename Component, typename... Other, typename... Exclude>
- [[nodiscard]] basic_view<entity_type, get_t<Component, Other...>, exclude_t<Exclude...>> view(exclude_t<Exclude...> = {}) {
- return {assure<std::remove_const_t<Component>>(), assure<std::remove_const_t<Other>>()..., assure<Exclude>()...};
- }
- /**
- * @brief Returns a group for the given components.
- *
- * Groups are created on the fly and share with the registry its internal
- * data structures. Feel free to discard them after the use.<br/>
- * Creating and destroying a group is an incredibly cheap operation. As a
- * rule of thumb, storing a group should never be an option.
- *
- * Groups support exclusion lists and can own types of components. The more
- * types are owned by a group, the faster it is to iterate entities and
- * components.<br/>
- * However, groups also affect some features of the registry such as the
- * creation and destruction of components.
- *
- * @note
- * Pools of components that are owned by a group cannot be sorted anymore.
- * The group takes the ownership of the pools and arrange components so as
- * to iterate them as fast as possible.
- *
- * @tparam Owned Types of components owned by the group.
- * @tparam Get Types of components observed by the group.
- * @tparam Exclude Types of components used to filter the group.
- * @return A newly created group.
- */
- template<typename... Owned, typename... Get, typename... Exclude>
- [[nodiscard]] basic_group<entity_type, owned_t<Owned...>, get_t<Get...>, exclude_t<Exclude...>> group(get_t<Get...>, exclude_t<Exclude...> = {}) {
- static_assert(sizeof...(Owned) + sizeof...(Get) > 0, "Exclusion-only groups are not supported");
- static_assert(sizeof...(Owned) + sizeof...(Get) + sizeof...(Exclude) > 1, "Single component groups are not allowed");
- using handler_type = group_handler<exclude_t<std::remove_const_t<Exclude>...>, get_t<std::remove_const_t<Get>...>, std::remove_const_t<Owned>...>;
- const auto cpools = std::forward_as_tuple(assure<std::remove_const_t<Owned>>()..., assure<std::remove_const_t<Get>>()...);
- constexpr auto size = sizeof...(Owned) + sizeof...(Get) + sizeof...(Exclude);
- handler_type *handler = nullptr;
- auto it = std::find_if(groups.cbegin(), groups.cend(), [size](const auto &gdata) {
- return gdata.size == size
- && (gdata.owned(type_hash<std::remove_const_t<Owned>>::value()) && ...)
- && (gdata.get(type_hash<std::remove_const_t<Get>>::value()) && ...)
- && (gdata.exclude(type_hash<Exclude>::value()) && ...);
- });
- if(it != groups.cend()) {
- handler = static_cast<handler_type *>(it->group.get());
- } else {
- group_data candidate = {
- size,
- {new handler_type{}, [](void *instance) { delete static_cast<handler_type *>(instance); }},
- []([[maybe_unused]] const id_type ctype) ENTT_NOEXCEPT { return ((ctype == type_hash<std::remove_const_t<Owned>>::value()) || ...); },
- []([[maybe_unused]] const id_type ctype) ENTT_NOEXCEPT { return ((ctype == type_hash<std::remove_const_t<Get>>::value()) || ...); },
- []([[maybe_unused]] const id_type ctype) ENTT_NOEXCEPT { return ((ctype == type_hash<Exclude>::value()) || ...); },
- };
- handler = static_cast<handler_type *>(candidate.group.get());
- const void *maybe_valid_if = nullptr;
- const void *discard_if = nullptr;
- if constexpr(sizeof...(Owned) == 0) {
- groups.push_back(std::move(candidate));
- } else {
- [[maybe_unused]] auto has_conflict = [size](const auto &gdata) {
- const auto overlapping = (0u + ... + gdata.owned(type_hash<std::remove_const_t<Owned>>::value()));
- const auto sz = overlapping + (0u + ... + gdata.get(type_hash<std::remove_const_t<Get>>::value())) + (0u + ... + gdata.exclude(type_hash<Exclude>::value()));
- return !overlapping || ((sz == size) || (sz == gdata.size));
- };
- ENTT_ASSERT(std::all_of(groups.cbegin(), groups.cend(), std::move(has_conflict)), "Conflicting groups");
- const auto next = std::find_if_not(groups.cbegin(), groups.cend(), [size](const auto &gdata) {
- return !(0u + ... + gdata.owned(type_hash<std::remove_const_t<Owned>>::value())) || (size > gdata.size);
- });
- const auto prev = std::find_if(std::make_reverse_iterator(next), groups.crend(), [](const auto &gdata) {
- return (0u + ... + gdata.owned(type_hash<std::remove_const_t<Owned>>::value()));
- });
- maybe_valid_if = (next == groups.cend() ? maybe_valid_if : next->group.get());
- discard_if = (prev == groups.crend() ? discard_if : prev->group.get());
- groups.insert(next, std::move(candidate));
- }
- (on_construct<std::remove_const_t<Owned>>().before(maybe_valid_if).template connect<&handler_type::template maybe_valid_if<std::remove_const_t<Owned>>>(*handler), ...);
- (on_construct<std::remove_const_t<Get>>().before(maybe_valid_if).template connect<&handler_type::template maybe_valid_if<std::remove_const_t<Get>>>(*handler), ...);
- (on_destroy<Exclude>().before(maybe_valid_if).template connect<&handler_type::template maybe_valid_if<Exclude>>(*handler), ...);
- (on_destroy<std::remove_const_t<Owned>>().before(discard_if).template connect<&handler_type::discard_if>(*handler), ...);
- (on_destroy<std::remove_const_t<Get>>().before(discard_if).template connect<&handler_type::discard_if>(*handler), ...);
- (on_construct<Exclude>().before(discard_if).template connect<&handler_type::discard_if>(*handler), ...);
- if constexpr(sizeof...(Owned) == 0) {
- for(const auto entity: view<Owned..., Get...>(exclude<Exclude...>)) {
- handler->current.emplace(entity);
- }
- } else {
- // we cannot iterate backwards because we want to leave behind valid entities in case of owned types
- for(auto *first = std::get<0>(cpools).data(), *last = first + std::get<0>(cpools).size(); first != last; ++first) {
- handler->template maybe_valid_if<type_list_element_t<0, type_list<std::remove_const_t<Owned>...>>>(*this, *first);
- }
- }
- }
- return {handler->current, std::get<storage_type<std::remove_const_t<Owned>> &>(cpools)..., std::get<storage_type<std::remove_const_t<Get>> &>(cpools)...};
- }
- /*! @copydoc group */
- template<typename... Owned, typename... Get, typename... Exclude>
- [[nodiscard]] basic_group<entity_type, owned_t<std::add_const_t<Owned>...>, get_t<std::add_const_t<Get>...>, exclude_t<Exclude...>> group_if_exists(get_t<Get...>, exclude_t<Exclude...> = {}) const {
- auto it = std::find_if(groups.cbegin(), groups.cend(), [](const auto &gdata) {
- return gdata.size == (sizeof...(Owned) + sizeof...(Get) + sizeof...(Exclude))
- && (gdata.owned(type_hash<std::remove_const_t<Owned>>::value()) && ...)
- && (gdata.get(type_hash<std::remove_const_t<Get>>::value()) && ...)
- && (gdata.exclude(type_hash<Exclude>::value()) && ...);
- });
- if(it == groups.cend()) {
- return {};
- } else {
- using handler_type = group_handler<exclude_t<std::remove_const_t<Exclude>...>, get_t<std::remove_const_t<Get>...>, std::remove_const_t<Owned>...>;
- return {static_cast<handler_type *>(it->group.get())->current, assure<std::remove_const_t<Owned>>()..., assure<std::remove_const_t<Get>>()...};
- }
- }
- /*! @copydoc group */
- template<typename... Owned, typename... Exclude>
- [[nodiscard]] basic_group<entity_type, owned_t<Owned...>, get_t<>, exclude_t<Exclude...>> group(exclude_t<Exclude...> = {}) {
- return group<Owned...>(get_t<>{}, exclude<Exclude...>);
- }
- /*! @copydoc group */
- template<typename... Owned, typename... Exclude>
- [[nodiscard]] basic_group<entity_type, owned_t<std::add_const_t<Owned>...>, get_t<>, exclude_t<Exclude...>> group_if_exists(exclude_t<Exclude...> = {}) const {
- return group_if_exists<std::add_const_t<Owned>...>(get_t<>{}, exclude<Exclude...>);
- }
- /**
- * @brief Checks whether the given components belong to any group.
- * @tparam Component Types of components in which one is interested.
- * @return True if the pools of the given components are _free_, false
- * otherwise.
- */
- template<typename... Component>
- [[nodiscard]] bool owned() const {
- return std::any_of(groups.cbegin(), groups.cend(), [](auto &&gdata) { return (gdata.owned(type_hash<std::remove_const_t<Component>>::value()) || ...); });
- }
- /**
- * @brief Checks whether a group can be sorted.
- * @tparam Owned Types of components owned by the group.
- * @tparam Get Types of components observed by the group.
- * @tparam Exclude Types of components used to filter the group.
- * @return True if the group can be sorted, false otherwise.
- */
- template<typename... Owned, typename... Get, typename... Exclude>
- [[nodiscard]] bool sortable(const basic_group<entity_type, owned_t<Owned...>, get_t<Get...>, exclude_t<Exclude...>> &) ENTT_NOEXCEPT {
- constexpr auto size = sizeof...(Owned) + sizeof...(Get) + sizeof...(Exclude);
- auto pred = [size](const auto &gdata) { return (0u + ... + gdata.owned(type_hash<std::remove_const_t<Owned>>::value())) && (size < gdata.size); };
- return std::find_if(groups.cbegin(), groups.cend(), std::move(pred)) == groups.cend();
- }
- /**
- * @brief Sorts the elements of a given component.
- *
- * The order remains valid until a component of the given type is assigned
- * to or removed from an entity.<br/>
- * 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 Component &, const Component &);
- * @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 components owned by a group cannot be sorted.
- *
- * @tparam Component Type of components 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 Component, typename Compare, typename Sort = std_sort, typename... Args>
- void sort(Compare compare, Sort algo = Sort{}, Args &&...args) {
- ENTT_ASSERT(!owned<Component>(), "Cannot sort owned storage");
- auto &cpool = assure<Component>();
- 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 components in the same way.
- *
- * Being `To` and `From` the two sets, after invoking this function an
- * iterator for `To` returns elements according to the following rules:
- *
- * * All entities in `To` that are also in `From` are returned first
- * according to the order they have in `From`.
- * * All entities in `To` that are not in `From` are returned in no
- * particular order after all the other entities.
- *
- * Any subsequent change to `From` won't affect the order in `To`.
- *
- * @warning
- * Pools of components owned by a group cannot be sorted.
- *
- * @tparam To Type of components to sort.
- * @tparam From Type of components to use to sort.
- */
- template<typename To, typename From>
- void sort() {
- ENTT_ASSERT(!owned<To>(), "Cannot sort owned storage");
- assure<To>().respect(assure<From>());
- }
- /**
- * @brief Returns the context object, that is, a general purpose container.
- * @return The context object, that is, a general purpose container.
- */
- context &ctx() ENTT_NOEXCEPT {
- return vars;
- }
- /*! @copydoc ctx */
- const context &ctx() const ENTT_NOEXCEPT {
- return vars;
- }
- private:
- dense_map<id_type, std::unique_ptr<base_type>, identity> pools;
- std::vector<group_data> groups;
- std::vector<entity_type> entities;
- entity_type free_list;
- context vars;
- };
- } // namespace entt
- #endif
- namespace entt {
- /**
- * @brief Non-owning handle to an entity.
- *
- * Tiny wrapper around a registry and an entity.
- *
- * @tparam Entity A valid entity type (see entt_traits for more details).
- * @tparam Type Types to which to restrict the scope of a handle.
- */
- template<typename Entity, typename... Type>
- struct basic_handle {
- /*! @brief Type of registry accepted by the handle. */
- using registry_type = constness_as_t<basic_registry<std::remove_const_t<Entity>>, Entity>;
- /*! @brief Underlying entity identifier. */
- using entity_type = typename registry_type::entity_type;
- /*! @brief Underlying version type. */
- using version_type = typename registry_type::version_type;
- /*! @brief Unsigned integer type. */
- using size_type = typename registry_type::size_type;
- /*! @brief Constructs an invalid handle. */
- basic_handle() ENTT_NOEXCEPT
- : reg{},
- 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) ENTT_NOEXCEPT
- : reg{&ref},
- entt{value} {}
- /**
- * @brief Constructs a const handle from a non-const one.
- * @tparam Other A valid entity type (see entt_traits for more details).
- * @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 ENTT_NOEXCEPT {
- static_assert(std::is_same_v<Other, Entity> || std::is_same_v<std::remove_const_t<Other>, Entity>, "Invalid conversion between different handles");
- static_assert((sizeof...(Type) == 0 || ((sizeof...(Args) != 0 && sizeof...(Args) <= sizeof...(Type)) && ... && (type_list_contains_v<type_list<Type...>, Args>))), "Invalid conversion between different handles");
- return reg ? basic_handle<Other, Args...>{*reg, entt} : basic_handle<Other, Args...>{};
- }
- /**
- * @brief Converts a handle to its underlying entity.
- * @return The contained identifier.
- */
- [[nodiscard]] operator entity_type() const ENTT_NOEXCEPT {
- return entity();
- }
- /**
- * @brief Checks if a handle refers to non-null registry pointer and entity.
- * @return True if the handle refers to non-null registry and entity, false otherwise.
- */
- [[nodiscard]] explicit operator bool() const ENTT_NOEXCEPT {
- return reg && reg->valid(entt);
- }
- /**
- * @brief Checks if a handle refers to a valid entity or not.
- * @return True if the handle refers to a valid entity, false otherwise.
- */
- [[nodiscard]] bool valid() const {
- return reg->valid(entt);
- }
- /**
- * @brief Returns a pointer to the underlying registry, if any.
- * @return A pointer to the underlying registry, if any.
- */
- [[nodiscard]] registry_type *registry() const ENTT_NOEXCEPT {
- return reg;
- }
- /**
- * @brief Returns the entity associated with a handle.
- * @return The entity associated with the handle.
- */
- [[nodiscard]] entity_type entity() const ENTT_NOEXCEPT {
- return entt;
- }
- /**
- * @brief Destroys the entity associated with a handle.
- * @sa basic_registry::destroy
- */
- void destroy() {
- reg->destroy(entt);
- }
- /**
- * @brief Destroys the entity associated with a handle.
- * @sa basic_registry::destroy
- * @param version A desired version upon destruction.
- */
- void destroy(const version_type version) {
- reg->destroy(entt, version);
- }
- /**
- * @brief Assigns the given component to a handle.
- * @sa basic_registry::emplace
- * @tparam Component Type of component to create.
- * @tparam Args Types of arguments to use to construct the component.
- * @param args Parameters to use to initialize the component.
- * @return A reference to the newly created component.
- */
- template<typename Component, typename... Args>
- decltype(auto) emplace(Args &&...args) const {
- static_assert(((sizeof...(Type) == 0) || ... || std::is_same_v<Component, Type>), "Invalid type");
- return reg->template emplace<Component>(entt, std::forward<Args>(args)...);
- }
- /**
- * @brief Assigns or replaces the given component for a handle.
- * @sa basic_registry::emplace_or_replace
- * @tparam Component Type of component to assign or replace.
- * @tparam Args Types of arguments to use to construct the component.
- * @param args Parameters to use to initialize the component.
- * @return A reference to the newly created component.
- */
- template<typename Component, typename... Args>
- decltype(auto) emplace_or_replace(Args &&...args) const {
- static_assert(((sizeof...(Type) == 0) || ... || std::is_same_v<Component, Type>), "Invalid type");
- return reg->template emplace_or_replace<Component>(entt, std::forward<Args>(args)...);
- }
- /**
- * @brief Patches the given component for a handle.
- * @sa basic_registry::patch
- * @tparam Component Type of component to patch.
- * @tparam Func Types of the function objects to invoke.
- * @param func Valid function objects.
- * @return A reference to the patched component.
- */
- template<typename Component, typename... Func>
- decltype(auto) patch(Func &&...func) const {
- static_assert(((sizeof...(Type) == 0) || ... || std::is_same_v<Component, Type>), "Invalid type");
- return reg->template patch<Component>(entt, std::forward<Func>(func)...);
- }
- /**
- * @brief Replaces the given component for a handle.
- * @sa basic_registry::replace
- * @tparam Component Type of component to replace.
- * @tparam Args Types of arguments to use to construct the component.
- * @param args Parameters to use to initialize the component.
- * @return A reference to the component being replaced.
- */
- template<typename Component, typename... Args>
- decltype(auto) replace(Args &&...args) const {
- static_assert(((sizeof...(Type) == 0) || ... || std::is_same_v<Component, Type>), "Invalid type");
- return reg->template replace<Component>(entt, std::forward<Args>(args)...);
- }
- /**
- * @brief Removes the given components from a handle.
- * @sa basic_registry::remove
- * @tparam Component Types of components to remove.
- * @return The number of components actually removed.
- */
- template<typename... Component>
- size_type remove() const {
- static_assert(sizeof...(Type) == 0 || (type_list_contains_v<type_list<Type...>, Component> && ...), "Invalid type");
- return reg->template remove<Component...>(entt);
- }
- /**
- * @brief Erases the given components from a handle.
- * @sa basic_registry::erase
- * @tparam Component Types of components to erase.
- */
- template<typename... Component>
- void erase() const {
- static_assert(sizeof...(Type) == 0 || (type_list_contains_v<type_list<Type...>, Component> && ...), "Invalid type");
- reg->template erase<Component...>(entt);
- }
- /**
- * @brief Checks if a handle has all the given components.
- * @sa basic_registry::all_of
- * @tparam Component Components for which to perform the check.
- * @return True if the handle has all the components, false otherwise.
- */
- template<typename... Component>
- [[nodiscard]] decltype(auto) all_of() const {
- return reg->template all_of<Component...>(entt);
- }
- /**
- * @brief Checks if a handle has at least one of the given components.
- * @sa basic_registry::any_of
- * @tparam Component Components for which to perform the check.
- * @return True if the handle has at least one of the given components,
- * false otherwise.
- */
- template<typename... Component>
- [[nodiscard]] decltype(auto) any_of() const {
- return reg->template any_of<Component...>(entt);
- }
- /**
- * @brief Returns references to the given components for a handle.
- * @sa basic_registry::get
- * @tparam Component Types of components to get.
- * @return References to the components owned by the handle.
- */
- template<typename... Component>
- [[nodiscard]] decltype(auto) get() const {
- static_assert(sizeof...(Type) == 0 || (type_list_contains_v<type_list<Type...>, Component> && ...), "Invalid type");
- return reg->template get<Component...>(entt);
- }
- /**
- * @brief Returns a reference to the given component for a handle.
- * @sa basic_registry::get_or_emplace
- * @tparam Component Type of component to get.
- * @tparam Args Types of arguments to use to construct the component.
- * @param args Parameters to use to initialize the component.
- * @return Reference to the component owned by the handle.
- */
- template<typename Component, typename... Args>
- [[nodiscard]] decltype(auto) get_or_emplace(Args &&...args) const {
- static_assert(((sizeof...(Type) == 0) || ... || std::is_same_v<Component, Type>), "Invalid type");
- return reg->template get_or_emplace<Component>(entt, std::forward<Args>(args)...);
- }
- /**
- * @brief Returns pointers to the given components for a handle.
- * @sa basic_registry::try_get
- * @tparam Component Types of components to get.
- * @return Pointers to the components owned by the handle.
- */
- template<typename... Component>
- [[nodiscard]] auto try_get() const {
- static_assert(sizeof...(Type) == 0 || (type_list_contains_v<type_list<Type...>, Component> && ...), "Invalid type");
- return reg->template try_get<Component...>(entt);
- }
- /**
- * @brief Checks if a handle has components assigned.
- * @return True if the handle has no components assigned, false otherwise.
- */
- [[nodiscard]] bool orphan() const {
- return reg->orphan(entt);
- }
- /**
- * @brief Visits a handle and returns the pools for its components.
- *
- * The signature of the function should be equivalent to the following:
- *
- * @code{.cpp}
- * void(id_type, const basic_sparse_set<entity_type> &);
- * @endcode
- *
- * Returned pools are those that contain the entity associated with the
- * handle.
- *
- * @tparam Func Type of the function object to invoke.
- * @param func A valid function object.
- */
- template<typename Func>
- void visit(Func &&func) const {
- for(auto [id, storage]: reg->storage()) {
- if(storage.contains(entt)) {
- func(id, storage);
- }
- }
- }
- private:
- registry_type *reg;
- 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) ENTT_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) ENTT_NOEXCEPT {
- return !(lhs == rhs);
- }
- /**
- * @brief Deduction guide.
- * @tparam Entity A valid entity type (see entt_traits for more details).
- */
- template<typename Entity>
- basic_handle(basic_registry<Entity> &, Entity) -> basic_handle<Entity>;
- /**
- * @brief Deduction guide.
- * @tparam Entity A valid entity type (see entt_traits for more details).
- */
- template<typename Entity>
- basic_handle(const basic_registry<Entity> &, Entity) -> basic_handle<const Entity>;
- } // namespace entt
- #endif
- // #include "entity/helper.hpp"
- #ifndef ENTT_ENTITY_HELPER_HPP
- #define ENTT_ENTITY_HELPER_HPP
- #include <type_traits>
- // #include "../config/config.h"
- // #include "../core/fwd.hpp"
- // #include "../core/type_traits.hpp"
- // #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"
- // #include "../core/type_traits.hpp"
- // #include "fwd.hpp"
- namespace entt {
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- namespace internal {
- template<typename Ret, typename... Args>
- auto function_pointer(Ret (*)(Args...)) -> Ret (*)(Args...);
- template<typename Ret, typename Type, typename... Args, typename Other>
- auto function_pointer(Ret (*)(Type, Args...), Other &&) -> Ret (*)(Args...);
- template<typename Class, typename Ret, typename... Args, typename... Other>
- auto function_pointer(Ret (Class::*)(Args...), Other &&...) -> Ret (*)(Args...);
- template<typename Class, typename Ret, typename... Args, typename... Other>
- auto function_pointer(Ret (Class::*)(Args...) const, Other &&...) -> Ret (*)(Args...);
- template<typename Class, typename Type, typename... Other>
- auto function_pointer(Type Class::*, Other &&...) -> Type (*)();
- template<typename... Type>
- using function_pointer_t = decltype(internal::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
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /*! @brief Used to wrap a function or a member of a specified type. */
- template<auto>
- struct connect_arg_t {};
- /*! @brief Constant of type connect_arg_t used to disambiguate calls. */
- template<auto Func>
- inline constexpr connect_arg_t<Func> connect_arg{};
- /**
- * @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...)> {
- template<auto Candidate, std::size_t... Index>
- [[nodiscard]] auto wrap(std::index_sequence<Index...>) ENTT_NOEXCEPT {
- return [](const void *, Args... args) -> Ret {
- [[maybe_unused]] const auto arguments = std::forward_as_tuple(std::forward<Args>(args)...);
- return static_cast<Ret>(std::invoke(Candidate, std::forward<type_list_element_t<Index, type_list<Args...>>>(std::get<Index>(arguments))...));
- };
- }
- template<auto Candidate, typename Type, std::size_t... Index>
- [[nodiscard]] auto wrap(Type &, std::index_sequence<Index...>) ENTT_NOEXCEPT {
- return [](const void *payload, Args... args) -> Ret {
- [[maybe_unused]] const auto arguments = std::forward_as_tuple(std::forward<Args>(args)...);
- Type *curr = static_cast<Type *>(const_cast<constness_as_t<void, Type> *>(payload));
- return static_cast<Ret>(std::invoke(Candidate, *curr, std::forward<type_list_element_t<Index, type_list<Args...>>>(std::get<Index>(arguments))...));
- };
- }
- template<auto Candidate, typename Type, std::size_t... Index>
- [[nodiscard]] auto wrap(Type *, std::index_sequence<Index...>) ENTT_NOEXCEPT {
- return [](const void *payload, Args... args) -> Ret {
- [[maybe_unused]] const auto arguments = std::forward_as_tuple(std::forward<Args>(args)...);
- Type *curr = static_cast<Type *>(const_cast<constness_as_t<void, Type> *>(payload));
- return static_cast<Ret>(std::invoke(Candidate, curr, std::forward<type_list_element_t<Index, type_list<Args...>>>(std::get<Index>(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() ENTT_NOEXCEPT
- : instance{nullptr},
- fn{nullptr} {}
- /**
- * @brief Constructs a delegate and connects a free function or an unbound
- * member.
- * @tparam Candidate Function or member to connect to the delegate.
- */
- template<auto Candidate>
- delegate(connect_arg_t<Candidate>) ENTT_NOEXCEPT {
- connect<Candidate>();
- }
- /**
- * @brief Constructs a delegate and connects a free function with payload or
- * a bound member.
- * @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 object that fits the purpose.
- */
- template<auto Candidate, typename Type>
- delegate(connect_arg_t<Candidate>, Type &&value_or_instance) ENTT_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) ENTT_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() ENTT_NOEXCEPT {
- instance = nullptr;
- if constexpr(std::is_invocable_r_v<Ret, decltype(Candidate), Args...>) {
- fn = [](const void *, Args... args) -> Ret {
- 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) ENTT_NOEXCEPT {
- instance = &value_or_instance;
- if constexpr(std::is_invocable_r_v<Ret, decltype(Candidate), Type &, Args...>) {
- fn = [](const void *payload, Args... args) -> Ret {
- 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) ENTT_NOEXCEPT {
- instance = value_or_instance;
- if constexpr(std::is_invocable_r_v<Ret, decltype(Candidate), Type *, Args...>) {
- fn = [](const void *payload, Args... args) -> Ret {
- 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) ENTT_NOEXCEPT {
- instance = payload;
- fn = function;
- }
- /**
- * @brief Resets a delegate.
- *
- * After a reset, a delegate cannot be invoked anymore.
- */
- void reset() ENTT_NOEXCEPT {
- instance = nullptr;
- fn = nullptr;
- }
- /**
- * @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 ENTT_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 ENTT_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 ENTT_NOEXCEPT {
- return fn == other.fn && instance == other.instance;
- }
- private:
- const void *instance;
- function_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) ENTT_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"
- // #include "registry.hpp"
- namespace entt {
- /**
- * @brief Converts a registry to a view.
- * @tparam Entity A valid entity type (see entt_traits for more details).
- */
- template<typename Entity>
- struct as_view {
- /*! @brief Underlying entity identifier. */
- using entity_type = std::remove_const_t<Entity>;
- /*! @brief Type of registry to convert. */
- using registry_type = constness_as_t<basic_registry<entity_type>, Entity>;
- /**
- * @brief Constructs a converter for a given registry.
- * @param source A valid reference to a registry.
- */
- as_view(registry_type &source) ENTT_NOEXCEPT: reg{source} {}
- /**
- * @brief Conversion function from a registry to a view.
- * @tparam Exclude Types of components used to filter the view.
- * @tparam Component Type of components used to construct the view.
- * @return A newly created view.
- */
- template<typename Exclude, typename... Component>
- operator basic_view<entity_type, get_t<Component...>, Exclude>() const {
- return reg.template view<Component...>(Exclude{});
- }
- private:
- registry_type ®
- };
- /**
- * @brief Deduction guide.
- * @tparam Entity A valid entity type (see entt_traits for more details).
- */
- template<typename Entity>
- as_view(basic_registry<Entity> &) -> as_view<Entity>;
- /**
- * @brief Deduction guide.
- * @tparam Entity A valid entity type (see entt_traits for more details).
- */
- template<typename Entity>
- as_view(const basic_registry<Entity> &) -> as_view<const Entity>;
- /**
- * @brief Converts a registry to a group.
- * @tparam Entity A valid entity type (see entt_traits for more details).
- */
- template<typename Entity>
- struct as_group {
- /*! @brief Underlying entity identifier. */
- using entity_type = std::remove_const_t<Entity>;
- /*! @brief Type of registry to convert. */
- using registry_type = constness_as_t<basic_registry<entity_type>, Entity>;
- /**
- * @brief Constructs a converter for a given registry.
- * @param source A valid reference to a registry.
- */
- as_group(registry_type &source) ENTT_NOEXCEPT: reg{source} {}
- /**
- * @brief Conversion function from a registry to a group.
- * @tparam Get Types of components observed by the group.
- * @tparam Exclude Types of components used to filter the group.
- * @tparam Owned Types of components owned by the group.
- * @return A newly created group.
- */
- template<typename Get, typename Exclude, typename... Owned>
- operator basic_group<entity_type, owned_t<Owned...>, Get, Exclude>() const {
- if constexpr(std::is_const_v<registry_type>) {
- return reg.template group_if_exists<Owned...>(Get{}, Exclude{});
- } else {
- return reg.template group<Owned...>(Get{}, Exclude{});
- }
- }
- private:
- registry_type ®
- };
- /**
- * @brief Deduction guide.
- * @tparam Entity A valid entity type (see entt_traits for more details).
- */
- template<typename Entity>
- as_group(basic_registry<Entity> &) -> as_group<Entity>;
- /**
- * @brief Deduction guide.
- * @tparam Entity A valid entity type (see entt_traits for more details).
- */
- template<typename Entity>
- as_group(const basic_registry<Entity> &) -> as_group<const Entity>;
- /**
- * @brief Helper to create a listener that directly invokes a member function.
- * @tparam Member Member function to invoke on a component of the given type.
- * @tparam Entity A valid entity type (see entt_traits for more details).
- * @param reg A registry that contains the given entity and its components.
- * @param entt Entity from which to get the component.
- */
- template<auto Member, typename Entity = entity>
- void invoke(basic_registry<Entity> ®, const Entity entt) {
- static_assert(std::is_member_function_pointer_v<decltype(Member)>, "Invalid pointer to non-static member function");
- delegate<void(basic_registry<Entity> &, const Entity)> func;
- func.template connect<Member>(reg.template get<member_class_t<decltype(Member)>>(entt));
- func(reg, entt);
- }
- /**
- * @brief Returns the entity associated with a given component.
- *
- * @warning
- * Currently, this function only works correctly with the default pool as it
- * makes assumptions about how the components are laid out.
- *
- * @tparam Entity A valid entity type (see entt_traits for more details).
- * @tparam Component Type of component.
- * @param reg A registry that contains the given entity and its components.
- * @param instance A valid component instance.
- * @return The entity associated with the given component.
- */
- template<typename Entity, typename Component>
- Entity to_entity(const basic_registry<Entity> ®, const Component &instance) {
- const auto &storage = reg.template storage<Component>();
- const typename basic_registry<Entity>::base_type &base = storage;
- const auto *addr = std::addressof(instance);
- for(auto it = base.rbegin(), last = base.rend(); it < last; it += ENTT_PACKED_PAGE) {
- if(const auto dist = (addr - std::addressof(storage.get(*it))); dist >= 0 && dist < ENTT_PACKED_PAGE) {
- return *(it + dist);
- }
- }
- return null;
- }
- } // namespace entt
- #endif
- // #include "entity/observer.hpp"
- #ifndef ENTT_ENTITY_OBSERVER_HPP
- #define ENTT_ENTITY_OBSERVER_HPP
- #include <cstddef>
- #include <cstdint>
- #include <limits>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- // #include "../core/type_traits.hpp"
- // #include "../signal/delegate.hpp"
- // #include "entity.hpp"
- // #include "fwd.hpp"
- // #include "registry.hpp"
- // #include "storage.hpp"
- // #include "utility.hpp"
- namespace entt {
- /*! @brief Grouping matcher. */
- template<typename...>
- struct matcher {};
- /**
- * @brief Collector.
- *
- * Primary template isn't defined on purpose. All the specializations give a
- * compile-time error, but for a few reasonable cases.
- */
- template<typename...>
- struct basic_collector;
- /**
- * @brief Collector.
- *
- * A collector contains a set of rules (literally, matchers) to use to track
- * entities.<br/>
- * Its main purpose is to generate a descriptor that allows an observer to know
- * how to connect to a registry.
- */
- template<>
- struct basic_collector<> {
- /**
- * @brief Adds a grouping matcher to the collector.
- * @tparam AllOf Types of components tracked by the matcher.
- * @tparam NoneOf Types of components used to filter out entities.
- * @return The updated collector.
- */
- template<typename... AllOf, typename... NoneOf>
- static constexpr auto group(exclude_t<NoneOf...> = {}) ENTT_NOEXCEPT {
- return basic_collector<matcher<type_list<>, type_list<>, type_list<NoneOf...>, AllOf...>>{};
- }
- /**
- * @brief Adds an observing matcher to the collector.
- * @tparam AnyOf Type of component for which changes should be detected.
- * @return The updated collector.
- */
- template<typename AnyOf>
- static constexpr auto update() ENTT_NOEXCEPT {
- return basic_collector<matcher<type_list<>, type_list<>, AnyOf>>{};
- }
- };
- /**
- * @brief Collector.
- * @copydetails basic_collector<>
- * @tparam Reject Untracked types used to filter out entities.
- * @tparam Require Untracked types required by the matcher.
- * @tparam Rule Specific details of the current matcher.
- * @tparam Other Other matchers.
- */
- template<typename... Reject, typename... Require, typename... Rule, typename... Other>
- struct basic_collector<matcher<type_list<Reject...>, type_list<Require...>, Rule...>, Other...> {
- /*! @brief Current matcher. */
- using current_type = matcher<type_list<Reject...>, type_list<Require...>, Rule...>;
- /**
- * @brief Adds a grouping matcher to the collector.
- * @tparam AllOf Types of components tracked by the matcher.
- * @tparam NoneOf Types of components used to filter out entities.
- * @return The updated collector.
- */
- template<typename... AllOf, typename... NoneOf>
- static constexpr auto group(exclude_t<NoneOf...> = {}) ENTT_NOEXCEPT {
- return basic_collector<matcher<type_list<>, type_list<>, type_list<NoneOf...>, AllOf...>, current_type, Other...>{};
- }
- /**
- * @brief Adds an observing matcher to the collector.
- * @tparam AnyOf Type of component for which changes should be detected.
- * @return The updated collector.
- */
- template<typename AnyOf>
- static constexpr auto update() ENTT_NOEXCEPT {
- return basic_collector<matcher<type_list<>, type_list<>, AnyOf>, current_type, Other...>{};
- }
- /**
- * @brief Updates the filter of the last added matcher.
- * @tparam AllOf Types of components required by the matcher.
- * @tparam NoneOf Types of components used to filter out entities.
- * @return The updated collector.
- */
- template<typename... AllOf, typename... NoneOf>
- static constexpr auto where(exclude_t<NoneOf...> = {}) ENTT_NOEXCEPT {
- using extended_type = matcher<type_list<Reject..., NoneOf...>, type_list<Require..., AllOf...>, Rule...>;
- return basic_collector<extended_type, Other...>{};
- }
- };
- /*! @brief Variable template used to ease the definition of collectors. */
- inline constexpr basic_collector<> collector{};
- /**
- * @brief Observer.
- *
- * An observer returns all the entities and only the entities that fit the
- * requirements of at least one matcher. Moreover, it's guaranteed that the
- * entity list is tightly packed in memory for fast iterations.<br/>
- * In general, observers don't stay true to the order of any set of components.
- *
- * Observers work mainly with two types of matchers, provided through a
- * collector:
- *
- * * Observing matcher: an observer will return at least all the living entities
- * for which one or more of the given components have been updated and not yet
- * destroyed.
- * * Grouping matcher: an observer will return at least all the living entities
- * that would have entered the given group if it existed and that would have
- * not yet left it.
- *
- * If an entity respects the requirements of multiple matchers, it will be
- * returned once and only once by the observer in any case.
- *
- * Matchers support also filtering by means of a _where_ clause that accepts
- * both a list of types and an exclusion list.<br/>
- * Whenever a matcher finds that an entity matches its requirements, the
- * condition of the filter is verified before to register the entity itself.
- * Moreover, a registered entity isn't returned by the observer if the condition
- * set by the filter is broken in the meantime.
- *
- * @b Important
- *
- * Iterators aren't invalidated if:
- *
- * * New instances of the given components are created and assigned to entities.
- * * The entity currently pointed is modified (as an example, if one of the
- * given components is removed from the entity to which the iterator points).
- * * The entity currently pointed is destroyed.
- *
- * In all the other cases, modifying the pools of the given components in any
- * way invalidates all the iterators and using them results in undefined
- * behavior.
- *
- * @warning
- * Lifetime of an observer doesn't necessarily have to overcome that of the
- * registry to which it is connected. However, the observer must be disconnected
- * from the registry before being destroyed to avoid crashes due to dangling
- * pointers.
- *
- * @tparam Entity A valid entity type (see entt_traits for more details).
- */
- template<typename Entity>
- class basic_observer {
- using payload_type = std::uint32_t;
- template<typename>
- struct matcher_handler;
- template<typename... Reject, typename... Require, typename AnyOf>
- struct matcher_handler<matcher<type_list<Reject...>, type_list<Require...>, AnyOf>> {
- template<std::size_t Index>
- static void maybe_valid_if(basic_observer &obs, basic_registry<Entity> ®, const Entity entt) {
- if(reg.template all_of<Require...>(entt) && !reg.template any_of<Reject...>(entt)) {
- if(!obs.storage.contains(entt)) {
- obs.storage.emplace(entt);
- }
- obs.storage.get(entt) |= (1 << Index);
- }
- }
- template<std::size_t Index>
- static void discard_if(basic_observer &obs, basic_registry<Entity> &, const Entity entt) {
- if(obs.storage.contains(entt) && !(obs.storage.get(entt) &= (~(1 << Index)))) {
- obs.storage.erase(entt);
- }
- }
- template<std::size_t Index>
- static void connect(basic_observer &obs, basic_registry<Entity> ®) {
- (reg.template on_destroy<Require>().template connect<&discard_if<Index>>(obs), ...);
- (reg.template on_construct<Reject>().template connect<&discard_if<Index>>(obs), ...);
- reg.template on_update<AnyOf>().template connect<&maybe_valid_if<Index>>(obs);
- reg.template on_destroy<AnyOf>().template connect<&discard_if<Index>>(obs);
- }
- static void disconnect(basic_observer &obs, basic_registry<Entity> ®) {
- (reg.template on_destroy<Require>().disconnect(obs), ...);
- (reg.template on_construct<Reject>().disconnect(obs), ...);
- reg.template on_update<AnyOf>().disconnect(obs);
- reg.template on_destroy<AnyOf>().disconnect(obs);
- }
- };
- template<typename... Reject, typename... Require, typename... NoneOf, typename... AllOf>
- struct matcher_handler<matcher<type_list<Reject...>, type_list<Require...>, type_list<NoneOf...>, AllOf...>> {
- template<std::size_t Index, typename... Ignore>
- static void maybe_valid_if(basic_observer &obs, basic_registry<Entity> ®, const Entity entt) {
- auto condition = [®, entt]() {
- if constexpr(sizeof...(Ignore) == 0) {
- return reg.template all_of<AllOf..., Require...>(entt) && !reg.template any_of<NoneOf..., Reject...>(entt);
- } else {
- return reg.template all_of<AllOf..., Require...>(entt) && ((std::is_same_v<Ignore..., NoneOf> || !reg.template any_of<NoneOf>(entt)) && ...) && !reg.template any_of<Reject...>(entt);
- }
- };
- if(condition()) {
- if(!obs.storage.contains(entt)) {
- obs.storage.emplace(entt);
- }
- obs.storage.get(entt) |= (1 << Index);
- }
- }
- template<std::size_t Index>
- static void discard_if(basic_observer &obs, basic_registry<Entity> &, const Entity entt) {
- if(obs.storage.contains(entt) && !(obs.storage.get(entt) &= (~(1 << Index)))) {
- obs.storage.erase(entt);
- }
- }
- template<std::size_t Index>
- static void connect(basic_observer &obs, basic_registry<Entity> ®) {
- (reg.template on_destroy<Require>().template connect<&discard_if<Index>>(obs), ...);
- (reg.template on_construct<Reject>().template connect<&discard_if<Index>>(obs), ...);
- (reg.template on_construct<AllOf>().template connect<&maybe_valid_if<Index>>(obs), ...);
- (reg.template on_destroy<NoneOf>().template connect<&maybe_valid_if<Index, NoneOf>>(obs), ...);
- (reg.template on_destroy<AllOf>().template connect<&discard_if<Index>>(obs), ...);
- (reg.template on_construct<NoneOf>().template connect<&discard_if<Index>>(obs), ...);
- }
- static void disconnect(basic_observer &obs, basic_registry<Entity> ®) {
- (reg.template on_destroy<Require>().disconnect(obs), ...);
- (reg.template on_construct<Reject>().disconnect(obs), ...);
- (reg.template on_construct<AllOf>().disconnect(obs), ...);
- (reg.template on_destroy<NoneOf>().disconnect(obs), ...);
- (reg.template on_destroy<AllOf>().disconnect(obs), ...);
- (reg.template on_construct<NoneOf>().disconnect(obs), ...);
- }
- };
- template<typename... Matcher>
- static void disconnect(basic_registry<Entity> ®, basic_observer &obs) {
- (matcher_handler<Matcher>::disconnect(obs, reg), ...);
- }
- template<typename... Matcher, std::size_t... Index>
- void connect(basic_registry<Entity> ®, std::index_sequence<Index...>) {
- static_assert(sizeof...(Matcher) < std::numeric_limits<payload_type>::digits, "Too many matchers");
- (matcher_handler<Matcher>::template connect<Index>(*this, reg), ...);
- release.template connect<&basic_observer::disconnect<Matcher...>>(reg);
- }
- public:
- /*! @brief Underlying entity identifier. */
- using entity_type = Entity;
- /*! @brief Unsigned integer type. */
- using size_type = std::size_t;
- /*! @brief Random access iterator type. */
- using iterator = typename basic_sparse_set<Entity>::iterator;
- /*! @brief Default constructor. */
- basic_observer()
- : release{},
- storage{} {}
- /*! @brief Default copy constructor, deleted on purpose. */
- basic_observer(const basic_observer &) = delete;
- /*! @brief Default move constructor, deleted on purpose. */
- basic_observer(basic_observer &&) = delete;
- /**
- * @brief Creates an observer and connects it to a given registry.
- * @tparam Matcher Types of matchers to use to initialize the observer.
- * @param reg A valid reference to a registry.
- */
- template<typename... Matcher>
- basic_observer(basic_registry<entity_type> ®, basic_collector<Matcher...>)
- : basic_observer{} {
- connect<Matcher...>(reg, std::index_sequence_for<Matcher...>{});
- }
- /*! @brief Default destructor. */
- ~basic_observer() = default;
- /**
- * @brief Default copy assignment operator, deleted on purpose.
- * @return This observer.
- */
- basic_observer &operator=(const basic_observer &) = delete;
- /**
- * @brief Default move assignment operator, deleted on purpose.
- * @return This observer.
- */
- basic_observer &operator=(basic_observer &&) = delete;
- /**
- * @brief Connects an observer to a given registry.
- * @tparam Matcher Types of matchers to use to initialize the observer.
- * @param reg A valid reference to a registry.
- */
- template<typename... Matcher>
- void connect(basic_registry<entity_type> ®, basic_collector<Matcher...>) {
- disconnect();
- connect<Matcher...>(reg, std::index_sequence_for<Matcher...>{});
- storage.clear();
- }
- /*! @brief Disconnects an observer from the registry it keeps track of. */
- void disconnect() {
- if(release) {
- release(*this);
- release.reset();
- }
- }
- /**
- * @brief Returns the number of elements in an observer.
- * @return Number of elements.
- */
- [[nodiscard]] size_type size() const ENTT_NOEXCEPT {
- return storage.size();
- }
- /**
- * @brief Checks whether an observer is empty.
- * @return True if the observer is empty, false otherwise.
- */
- [[nodiscard]] bool empty() const ENTT_NOEXCEPT {
- return storage.empty();
- }
- /**
- * @brief Direct access to the list of entities of the observer.
- *
- * The returned pointer is such that range `[data(), data() + size())` is
- * always a valid range, even if the container is empty.
- *
- * @note
- * Entities are in the reverse order as returned by the `begin`/`end`
- * iterators.
- *
- * @return A pointer to the array of entities.
- */
- [[nodiscard]] const entity_type *data() const ENTT_NOEXCEPT {
- return storage.data();
- }
- /**
- * @brief Returns an iterator to the first entity of the observer.
- *
- * The returned iterator points to the first entity of the observer. If the
- * container is empty, the returned iterator will be equal to `end()`.
- *
- * @return An iterator to the first entity of the observer.
- */
- [[nodiscard]] iterator begin() const ENTT_NOEXCEPT {
- return storage.basic_sparse_set<entity_type>::begin();
- }
- /**
- * @brief Returns an iterator that is past the last entity of the observer.
- *
- * The returned iterator points to the entity following the last entity of
- * the observer. Attempting to dereference the returned iterator results in
- * undefined behavior.
- *
- * @return An iterator to the entity following the last entity of the
- * observer.
- */
- [[nodiscard]] iterator end() const ENTT_NOEXCEPT {
- return storage.basic_sparse_set<entity_type>::end();
- }
- /*! @brief Clears the underlying container. */
- void clear() ENTT_NOEXCEPT {
- storage.clear();
- }
- /**
- * @brief Iterates entities and applies the given function object to them.
- *
- * The function object is invoked for each entity.<br/>
- * The signature of the function must be equivalent to the following form:
- *
- * @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);
- }
- }
- /**
- * @brief Iterates entities and applies the given function object to them,
- * then clears the observer.
- *
- * @sa each
- *
- * @tparam Func Type of the function object to invoke.
- * @param func A valid function object.
- */
- template<typename Func>
- void each(Func func) {
- std::as_const(*this).each(std::move(func));
- clear();
- }
- private:
- delegate<void(basic_observer &)> release;
- basic_storage<entity_type, payload_type> storage;
- };
- } // namespace entt
- #endif
- // #include "entity/organizer.hpp"
- #ifndef ENTT_ENTITY_ORGANIZER_HPP
- #define ENTT_ENTITY_ORGANIZER_HPP
- #include <algorithm>
- #include <cstddef>
- #include <type_traits>
- #include <utility>
- #include <vector>
- // #include "../container/dense_map.hpp"
- // #include "../core/type_info.hpp"
- // #include "../core/type_traits.hpp"
- // #include "../core/utility.hpp"
- // #include "fwd.hpp"
- // #include "helper.hpp"
- #ifndef ENTT_ENTITY_HELPER_HPP
- #define ENTT_ENTITY_HELPER_HPP
- #include <type_traits>
- // #include "../config/config.h"
- // #include "../core/fwd.hpp"
- // #include "../core/type_traits.hpp"
- // #include "../signal/delegate.hpp"
- // #include "fwd.hpp"
- // #include "registry.hpp"
- namespace entt {
- /**
- * @brief Converts a registry to a view.
- * @tparam Entity A valid entity type (see entt_traits for more details).
- */
- template<typename Entity>
- struct as_view {
- /*! @brief Underlying entity identifier. */
- using entity_type = std::remove_const_t<Entity>;
- /*! @brief Type of registry to convert. */
- using registry_type = constness_as_t<basic_registry<entity_type>, Entity>;
- /**
- * @brief Constructs a converter for a given registry.
- * @param source A valid reference to a registry.
- */
- as_view(registry_type &source) ENTT_NOEXCEPT: reg{source} {}
- /**
- * @brief Conversion function from a registry to a view.
- * @tparam Exclude Types of components used to filter the view.
- * @tparam Component Type of components used to construct the view.
- * @return A newly created view.
- */
- template<typename Exclude, typename... Component>
- operator basic_view<entity_type, get_t<Component...>, Exclude>() const {
- return reg.template view<Component...>(Exclude{});
- }
- private:
- registry_type ®
- };
- /**
- * @brief Deduction guide.
- * @tparam Entity A valid entity type (see entt_traits for more details).
- */
- template<typename Entity>
- as_view(basic_registry<Entity> &) -> as_view<Entity>;
- /**
- * @brief Deduction guide.
- * @tparam Entity A valid entity type (see entt_traits for more details).
- */
- template<typename Entity>
- as_view(const basic_registry<Entity> &) -> as_view<const Entity>;
- /**
- * @brief Converts a registry to a group.
- * @tparam Entity A valid entity type (see entt_traits for more details).
- */
- template<typename Entity>
- struct as_group {
- /*! @brief Underlying entity identifier. */
- using entity_type = std::remove_const_t<Entity>;
- /*! @brief Type of registry to convert. */
- using registry_type = constness_as_t<basic_registry<entity_type>, Entity>;
- /**
- * @brief Constructs a converter for a given registry.
- * @param source A valid reference to a registry.
- */
- as_group(registry_type &source) ENTT_NOEXCEPT: reg{source} {}
- /**
- * @brief Conversion function from a registry to a group.
- * @tparam Get Types of components observed by the group.
- * @tparam Exclude Types of components used to filter the group.
- * @tparam Owned Types of components owned by the group.
- * @return A newly created group.
- */
- template<typename Get, typename Exclude, typename... Owned>
- operator basic_group<entity_type, owned_t<Owned...>, Get, Exclude>() const {
- if constexpr(std::is_const_v<registry_type>) {
- return reg.template group_if_exists<Owned...>(Get{}, Exclude{});
- } else {
- return reg.template group<Owned...>(Get{}, Exclude{});
- }
- }
- private:
- registry_type ®
- };
- /**
- * @brief Deduction guide.
- * @tparam Entity A valid entity type (see entt_traits for more details).
- */
- template<typename Entity>
- as_group(basic_registry<Entity> &) -> as_group<Entity>;
- /**
- * @brief Deduction guide.
- * @tparam Entity A valid entity type (see entt_traits for more details).
- */
- template<typename Entity>
- as_group(const basic_registry<Entity> &) -> as_group<const Entity>;
- /**
- * @brief Helper to create a listener that directly invokes a member function.
- * @tparam Member Member function to invoke on a component of the given type.
- * @tparam Entity A valid entity type (see entt_traits for more details).
- * @param reg A registry that contains the given entity and its components.
- * @param entt Entity from which to get the component.
- */
- template<auto Member, typename Entity = entity>
- void invoke(basic_registry<Entity> ®, const Entity entt) {
- static_assert(std::is_member_function_pointer_v<decltype(Member)>, "Invalid pointer to non-static member function");
- delegate<void(basic_registry<Entity> &, const Entity)> func;
- func.template connect<Member>(reg.template get<member_class_t<decltype(Member)>>(entt));
- func(reg, entt);
- }
- /**
- * @brief Returns the entity associated with a given component.
- *
- * @warning
- * Currently, this function only works correctly with the default pool as it
- * makes assumptions about how the components are laid out.
- *
- * @tparam Entity A valid entity type (see entt_traits for more details).
- * @tparam Component Type of component.
- * @param reg A registry that contains the given entity and its components.
- * @param instance A valid component instance.
- * @return The entity associated with the given component.
- */
- template<typename Entity, typename Component>
- Entity to_entity(const basic_registry<Entity> ®, const Component &instance) {
- const auto &storage = reg.template storage<Component>();
- const typename basic_registry<Entity>::base_type &base = storage;
- const auto *addr = std::addressof(instance);
- for(auto it = base.rbegin(), last = base.rend(); it < last; it += ENTT_PACKED_PAGE) {
- if(const auto dist = (addr - std::addressof(storage.get(*it))); dist >= 0 && dist < ENTT_PACKED_PAGE) {
- return *(it + dist);
- }
- }
- return null;
- }
- } // namespace entt
- #endif
- namespace entt {
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- namespace internal {
- template<typename>
- struct is_view: std::false_type {};
- template<typename Entity, typename... Component, typename... Exclude>
- struct is_view<basic_view<Entity, get_t<Component...>, exclude_t<Exclude...>>>: std::true_type {};
- template<typename Type>
- inline constexpr bool is_view_v = is_view<Type>::value;
- template<typename Type, typename Override>
- struct unpack_type {
- using ro = std::conditional_t<
- type_list_contains_v<Override, std::add_const_t<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, std::add_const_t<Type>>),
- type_list<Type>,
- type_list<>>;
- };
- template<typename Entity, typename... Override>
- struct unpack_type<basic_registry<Entity>, type_list<Override...>> {
- using ro = type_list<>;
- using rw = type_list<>;
- };
- template<typename Entity, typename... Override>
- struct unpack_type<const basic_registry<Entity>, type_list<Override...>>
- : unpack_type<basic_registry<Entity>, type_list<Override...>> {};
- template<typename Entity, typename... Component, typename... Exclude, typename... Override>
- struct unpack_type<basic_view<Entity, get_t<Component...>, exclude_t<Exclude...>>, type_list<Override...>> {
- using ro = type_list_cat_t<type_list<Exclude...>, typename unpack_type<Component, type_list<Override...>>::ro...>;
- using rw = type_list_cat_t<typename unpack_type<Component, type_list<Override...>>::rw...>;
- };
- template<typename Entity, typename... Component, typename... Exclude, typename... Override>
- struct unpack_type<const basic_view<Entity, get_t<Component...>, exclude_t<Exclude...>>, type_list<Override...>>
- : unpack_type<basic_view<Entity, get_t<Component...>, exclude_t<Exclude...>>, type_list<Override...>> {};
- template<typename, typename>
- struct resource_traits;
- template<typename... Args, typename... Req>
- struct resource_traits<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...>;
- };
- template<typename... Req, typename Ret, typename... Args>
- resource_traits<type_list<std::remove_reference_t<Args>...>, type_list<Req...>> free_function_to_resource_traits(Ret (*)(Args...));
- template<typename... Req, typename Ret, typename Type, typename... Args>
- resource_traits<type_list<std::remove_reference_t<Args>...>, type_list<Req...>> constrained_function_to_resource_traits(Ret (*)(Type &, Args...));
- template<typename... Req, typename Ret, typename Class, typename... Args>
- resource_traits<type_list<std::remove_reference_t<Args>...>, type_list<Req...>> constrained_function_to_resource_traits(Ret (Class::*)(Args...));
- template<typename... Req, typename Ret, typename Class, typename... Args>
- resource_traits<type_list<std::remove_reference_t<Args>...>, type_list<Req...>> constrained_function_to_resource_traits(Ret (Class::*)(Args...) const);
- } // namespace internal
- /**
- * Internal details not to be documented.
- * @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 Entity A valid entity type (see entt_traits for more details).
- */
- template<typename Entity>
- class basic_organizer final {
- using callback_type = void(const void *, basic_registry<Entity> &);
- using prepare_type = void(basic_registry<Entity> &);
- 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(basic_registry<Entity> ®) {
- if constexpr(std::is_same_v<Type, basic_registry<Entity>>) {
- return reg;
- } else if constexpr(internal::is_view_v<Type>) {
- return as_view{reg};
- } else {
- return reg.ctx().template emplace<std::remove_reference_t<Type>>();
- }
- }
- template<typename... Args>
- [[nodiscard]] static auto to_args(basic_registry<Entity> ®, type_list<Args...>) {
- return std::tuple<decltype(extract<Args>(reg))...>(extract<Args>(reg)...);
- }
- template<typename... Type>
- 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 {
- const type_info *info[sizeof...(Type)]{&type_id<Type>()...};
- const auto length = (std::min)(count, sizeof...(Type));
- std::copy_n(info, length, buffer);
- return length;
- }
- }
- template<typename... RO, typename... RW>
- void track_dependencies(std::size_t index, const bool requires_registry, type_list<RO...>, type_list<RW...>) {
- dependencies[type_hash<basic_registry<Entity>>::value()].emplace_back(index, requires_registry || (sizeof...(RO) + sizeof...(RW) == 0u));
- (dependencies[type_hash<RO>::value()].emplace_back(index, false), ...);
- (dependencies[type_hash<RW>::value()].emplace_back(index, true), ...);
- }
- [[nodiscard]] std::vector<bool> adjacency_matrix() {
- const auto length = vertices.size();
- std::vector<bool> edges(length * length, false);
- // creates the adjacency matrix
- for(const auto &deps: dependencies) {
- const auto last = deps.second.cend();
- auto it = deps.second.cbegin();
- while(it != last) {
- if(it->second) {
- // rw item
- if(auto curr = it++; it != last) {
- if(it->second) {
- edges[curr->first * length + it->first] = true;
- } else {
- if(const auto next = std::find_if(it, last, [](const auto &elem) { return elem.second; }); next != last) {
- for(; it != next; ++it) {
- edges[curr->first * length + it->first] = true;
- edges[it->first * length + next->first] = true;
- }
- } else {
- for(; it != next; ++it) {
- edges[curr->first * length + it->first] = true;
- }
- }
- }
- }
- } else {
- // ro item, possibly only on first iteration
- if(const auto next = std::find_if(it, last, [](const auto &elem) { return elem.second; }); next != last) {
- for(; it != next; ++it) {
- edges[it->first * length + next->first] = true;
- }
- } else {
- it = last;
- }
- }
- }
- }
- // computes the transitive closure
- for(std::size_t vk{}; vk < length; ++vk) {
- for(std::size_t vi{}; vi < length; ++vi) {
- for(std::size_t vj{}; vj < length; ++vj) {
- edges[vi * length + vj] = edges[vi * length + vj] || (edges[vi * length + vk] && edges[vk * length + vj]);
- }
- }
- }
- // applies the transitive reduction
- for(std::size_t vert{}; vert < length; ++vert) {
- edges[vert * length + vert] = false;
- }
- for(std::size_t vj{}; vj < length; ++vj) {
- for(std::size_t vi{}; vi < length; ++vi) {
- if(edges[vi * length + vj]) {
- for(std::size_t vk{}; vk < length; ++vk) {
- if(edges[vj * length + vk]) {
- edges[vi * length + vk] = false;
- }
- }
- }
- }
- }
- return edges;
- }
- public:
- /*! @brief Underlying entity identifier. */
- using entity_type = Entity;
- /*! @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 vtype True if the vertex is a top-level one, false otherwise.
- * @param data The data associated with the vertex.
- * @param edges The indices of the children in the adjacency list.
- */
- vertex(const bool vtype, vertex_data data, std::vector<std::size_t> edges)
- : is_top_level{vtype},
- node{std::move(data)},
- reachable{std::move(edges)} {}
- /**
- * @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.
- */
- size_type ro_dependency(const type_info **buffer, const std::size_t length) const ENTT_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.
- */
- size_type rw_dependency(const type_info **buffer, const std::size_t length) const ENTT_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.
- */
- size_type ro_count() const ENTT_NOEXCEPT {
- return node.ro_count;
- }
- /**
- * @brief Returns the number of writable resources of a vertex.
- * @return The number of writable resources of the vertex.
- */
- size_type rw_count() const ENTT_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.
- */
- bool top_level() const ENTT_NOEXCEPT {
- return is_top_level;
- }
- /**
- * @brief Returns a type info object associated with a vertex.
- * @return A properly initialized type info object.
- */
- const type_info &info() const ENTT_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.
- */
- const char *name() const ENTT_NOEXCEPT {
- return node.name;
- }
- /**
- * @brief Returns the function associated with a vertex.
- * @return The function associated with the vertex.
- */
- function_type *callback() const ENTT_NOEXCEPT {
- return node.callback;
- }
- /**
- * @brief Returns the payload associated with a vertex, if any.
- * @return The payload associated with the vertex, if any.
- */
- const void *data() const ENTT_NOEXCEPT {
- return node.payload;
- }
- /**
- * @brief Returns the list of nodes reachable from a given vertex.
- * @return The list of nodes reachable from the vertex.
- */
- const std::vector<std::size_t> &children() const ENTT_NOEXCEPT {
- return reachable;
- }
- /**
- * @brief Prepares a registry and assures that all required resources
- * are properly instantiated before using them.
- * @param reg A valid registry.
- */
- void prepare(basic_registry<entity_type> ®) const {
- node.prepare ? node.prepare(reg) : void();
- }
- private:
- bool is_top_level;
- vertex_data node;
- std::vector<std::size_t> reachable;
- };
- /**
- * @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<Req...>(Candidate));
- constexpr auto requires_registry = type_list_contains_v<typename resource_type::args, basic_registry<entity_type>>;
- callback_type *callback = +[](const void *, basic_registry<entity_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); },
- +[](basic_registry<entity_type> ®) { void(to_args(reg, typename resource_type::args{})); },
- &type_id<std::integral_constant<decltype(Candidate), Candidate>>()};
- track_dependencies(vertices.size(), requires_registry, 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<Req...>(Candidate));
- constexpr auto requires_registry = type_list_contains_v<typename resource_type::args, basic_registry<entity_type>>;
- callback_type *callback = +[](const void *payload, basic_registry<entity_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); },
- +[](basic_registry<entity_type> ®) { void(to_args(reg, typename resource_type::args{})); },
- &type_id<std::integral_constant<decltype(Candidate), Candidate>>()};
- track_dependencies(vertices.size(), requires_registry, 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<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.
- */
- std::vector<vertex> graph() {
- const auto edges = adjacency_matrix();
- // creates the adjacency list
- std::vector<vertex> adjacency_list{};
- adjacency_list.reserve(vertices.size());
- for(std::size_t col{}, length = vertices.size(); col < length; ++col) {
- std::vector<std::size_t> reachable{};
- const auto row = col * length;
- bool is_top_level = true;
- for(std::size_t next{}; next < length; ++next) {
- if(edges[row + next]) {
- reachable.push_back(next);
- }
- }
- for(std::size_t next{}; next < length && is_top_level; ++next) {
- is_top_level = !edges[next * length + col];
- }
- adjacency_list.emplace_back(is_top_level, vertices[col], std::move(reachable));
- }
- return adjacency_list;
- }
- /*! @brief Erases all elements from a container. */
- void clear() {
- dependencies.clear();
- vertices.clear();
- }
- private:
- dense_map<id_type, std::vector<std::pair<std::size_t, bool>>, identity> dependencies;
- std::vector<vertex_data> vertices;
- };
- } // namespace entt
- #endif
- // #include "entity/registry.hpp"
- #ifndef ENTT_ENTITY_REGISTRY_HPP
- #define ENTT_ENTITY_REGISTRY_HPP
- #include <algorithm>
- #include <cstddef>
- #include <iterator>
- #include <memory>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- #include <vector>
- // #include "../config/config.h"
- // #include "../container/dense_map.hpp"
- // #include "../core/algorithm.hpp"
- // #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 "component.hpp"
- // #include "entity.hpp"
- // #include "fwd.hpp"
- // #include "group.hpp"
- // #include "runtime_view.hpp"
- // #include "sparse_set.hpp"
- // #include "storage.hpp"
- // #include "utility.hpp"
- // #include "view.hpp"
- namespace entt {
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- namespace internal {
- template<typename It>
- class storage_proxy_iterator final {
- template<typename Other>
- friend class storage_proxy_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;
- storage_proxy_iterator() ENTT_NOEXCEPT
- : it{} {}
- storage_proxy_iterator(const It iter) ENTT_NOEXCEPT
- : it{iter} {}
- template<typename Other, typename = std::enable_if_t<!std::is_same_v<It, Other> && std::is_constructible_v<It, Other>>>
- storage_proxy_iterator(const storage_proxy_iterator<Other> &other) ENTT_NOEXCEPT
- : it{other.it} {}
- storage_proxy_iterator &operator++() ENTT_NOEXCEPT {
- return ++it, *this;
- }
- storage_proxy_iterator operator++(int) ENTT_NOEXCEPT {
- storage_proxy_iterator orig = *this;
- return ++(*this), orig;
- }
- storage_proxy_iterator &operator--() ENTT_NOEXCEPT {
- return --it, *this;
- }
- storage_proxy_iterator operator--(int) ENTT_NOEXCEPT {
- storage_proxy_iterator orig = *this;
- return operator--(), orig;
- }
- storage_proxy_iterator &operator+=(const difference_type value) ENTT_NOEXCEPT {
- it += value;
- return *this;
- }
- storage_proxy_iterator operator+(const difference_type value) const ENTT_NOEXCEPT {
- storage_proxy_iterator copy = *this;
- return (copy += value);
- }
- storage_proxy_iterator &operator-=(const difference_type value) ENTT_NOEXCEPT {
- return (*this += -value);
- }
- storage_proxy_iterator operator-(const difference_type value) const ENTT_NOEXCEPT {
- return (*this + -value);
- }
- [[nodiscard]] reference operator[](const difference_type value) const ENTT_NOEXCEPT {
- return {it[value].first, *it[value].second};
- }
- [[nodiscard]] reference operator*() const ENTT_NOEXCEPT {
- return {it->first, *it->second};
- }
- [[nodiscard]] pointer operator->() const ENTT_NOEXCEPT {
- return operator*();
- }
- template<typename ILhs, typename IRhs>
- friend std::ptrdiff_t operator-(const storage_proxy_iterator<ILhs> &, const storage_proxy_iterator<IRhs> &) ENTT_NOEXCEPT;
- template<typename ILhs, typename IRhs>
- friend bool operator==(const storage_proxy_iterator<ILhs> &, const storage_proxy_iterator<IRhs> &) ENTT_NOEXCEPT;
- template<typename ILhs, typename IRhs>
- friend bool operator<(const storage_proxy_iterator<ILhs> &, const storage_proxy_iterator<IRhs> &) ENTT_NOEXCEPT;
- private:
- It it;
- };
- template<typename ILhs, typename IRhs>
- [[nodiscard]] std::ptrdiff_t operator-(const storage_proxy_iterator<ILhs> &lhs, const storage_proxy_iterator<IRhs> &rhs) ENTT_NOEXCEPT {
- return lhs.it - rhs.it;
- }
- template<typename ILhs, typename IRhs>
- [[nodiscard]] bool operator==(const storage_proxy_iterator<ILhs> &lhs, const storage_proxy_iterator<IRhs> &rhs) ENTT_NOEXCEPT {
- return lhs.it == rhs.it;
- }
- template<typename ILhs, typename IRhs>
- [[nodiscard]] bool operator!=(const storage_proxy_iterator<ILhs> &lhs, const storage_proxy_iterator<IRhs> &rhs) ENTT_NOEXCEPT {
- return !(lhs == rhs);
- }
- template<typename ILhs, typename IRhs>
- [[nodiscard]] bool operator<(const storage_proxy_iterator<ILhs> &lhs, const storage_proxy_iterator<IRhs> &rhs) ENTT_NOEXCEPT {
- return lhs.it < rhs.it;
- }
- template<typename ILhs, typename IRhs>
- [[nodiscard]] bool operator>(const storage_proxy_iterator<ILhs> &lhs, const storage_proxy_iterator<IRhs> &rhs) ENTT_NOEXCEPT {
- return rhs < lhs;
- }
- template<typename ILhs, typename IRhs>
- [[nodiscard]] bool operator<=(const storage_proxy_iterator<ILhs> &lhs, const storage_proxy_iterator<IRhs> &rhs) ENTT_NOEXCEPT {
- return !(lhs > rhs);
- }
- template<typename ILhs, typename IRhs>
- [[nodiscard]] bool operator>=(const storage_proxy_iterator<ILhs> &lhs, const storage_proxy_iterator<IRhs> &rhs) ENTT_NOEXCEPT {
- return !(lhs < rhs);
- }
- struct registry_context {
- template<typename Type, typename... Args>
- Type &emplace_hint(const id_type id, Args &&...args) {
- return any_cast<Type &>(data.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_hint<Type>(type_id<Type>().hash(), std::forward<Args>(args)...);
- }
- template<typename Type>
- bool erase(const id_type id = type_id<Type>().hash()) {
- const auto it = data.find(id);
- return it != data.end() && it->second.type() == type_id<Type>() ? (data.erase(it), true) : false;
- }
- template<typename Type>
- [[nodiscard]] std::add_const_t<Type> &at(const id_type id = type_id<Type>().hash()) const {
- return any_cast<std::add_const_t<Type> &>(data.at(id));
- }
- template<typename Type>
- [[nodiscard]] Type &at(const id_type id = type_id<Type>().hash()) {
- return any_cast<Type &>(data.at(id));
- }
- template<typename Type>
- [[nodiscard]] std::add_const_t<Type> *find(const id_type id = type_id<Type>().hash()) const {
- const auto it = data.find(id);
- return it != data.cend() ? any_cast<std::add_const_t<Type>>(&it->second) : nullptr;
- }
- template<typename Type>
- [[nodiscard]] Type *find(const id_type id = type_id<Type>().hash()) {
- const auto it = data.find(id);
- return it != data.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 = data.find(id);
- return it != data.end() && it->second.type() == type_id<Type>();
- }
- private:
- dense_map<id_type, basic_any<0u>, identity> data;
- };
- } // namespace internal
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /**
- * @brief Fast and reliable entity-component system.
- * @tparam Entity A valid entity type (see entt_traits for more details).
- */
- template<typename Entity>
- class basic_registry {
- using entity_traits = entt_traits<Entity>;
- using basic_common_type = basic_sparse_set<Entity>;
- template<typename Component>
- using storage_type = typename storage_traits<Entity, Component>::storage_type;
- template<typename...>
- struct group_handler;
- template<typename... Exclude, typename... Get, typename... Owned>
- struct group_handler<exclude_t<Exclude...>, get_t<Get...>, Owned...> {
- // nasty workaround for an issue with the toolset v141 that doesn't accept a fold expression here
- static_assert(!std::disjunction_v<std::bool_constant<component_traits<Owned>::in_place_delete>...>, "Groups do not support in-place delete");
- std::conditional_t<sizeof...(Owned) == 0, basic_common_type, std::size_t> current{};
- template<typename Component>
- void maybe_valid_if(basic_registry &owner, const Entity entt) {
- [[maybe_unused]] const auto cpools = std::forward_as_tuple(owner.assure<Owned>()...);
- const auto is_valid = ((std::is_same_v<Component, Owned> || std::get<storage_type<Owned> &>(cpools).contains(entt)) && ...)
- && ((std::is_same_v<Component, Get> || owner.assure<Get>().contains(entt)) && ...)
- && ((std::is_same_v<Component, Exclude> || !owner.assure<Exclude>().contains(entt)) && ...);
- if constexpr(sizeof...(Owned) == 0) {
- if(is_valid && !current.contains(entt)) {
- current.emplace(entt);
- }
- } else {
- if(is_valid && !(std::get<0>(cpools).index(entt) < current)) {
- const auto pos = current++;
- (std::get<storage_type<Owned> &>(cpools).swap_elements(std::get<storage_type<Owned> &>(cpools).data()[pos], entt), ...);
- }
- }
- }
- void discard_if([[maybe_unused]] basic_registry &owner, const Entity entt) {
- if constexpr(sizeof...(Owned) == 0) {
- current.remove(entt);
- } else {
- if(const auto cpools = std::forward_as_tuple(owner.assure<Owned>()...); std::get<0>(cpools).contains(entt) && (std::get<0>(cpools).index(entt) < current)) {
- const auto pos = --current;
- (std::get<storage_type<Owned> &>(cpools).swap_elements(std::get<storage_type<Owned> &>(cpools).data()[pos], entt), ...);
- }
- }
- }
- };
- struct group_data {
- std::size_t size;
- std::unique_ptr<void, void (*)(void *)> group;
- bool (*owned)(const id_type) ENTT_NOEXCEPT;
- bool (*get)(const id_type) ENTT_NOEXCEPT;
- bool (*exclude)(const id_type) ENTT_NOEXCEPT;
- };
- template<typename Component>
- [[nodiscard]] auto &assure(const id_type id = type_hash<Component>::value()) {
- static_assert(std::is_same_v<Component, std::decay_t<Component>>, "Non-decayed types not allowed");
- auto &&cpool = pools[id];
- if(!cpool) {
- cpool.reset(new storage_type<Component>{});
- cpool->bind(forward_as_any(*this));
- }
- ENTT_ASSERT(cpool->type() == type_id<Component>(), "Unexpected type");
- return static_cast<storage_type<Component> &>(*cpool);
- }
- template<typename Component>
- [[nodiscard]] const auto &assure(const id_type id = type_hash<Component>::value()) const {
- static_assert(std::is_same_v<Component, std::decay_t<Component>>, "Non-decayed types not allowed");
- if(const auto it = pools.find(id); it != pools.cend()) {
- ENTT_ASSERT(it->second->type() == type_id<Component>(), "Unexpected type");
- return static_cast<const storage_type<Component> &>(*it->second);
- }
- static storage_type<Component> placeholder{};
- return placeholder;
- }
- auto generate_identifier(const std::size_t pos) ENTT_NOEXCEPT {
- ENTT_ASSERT(pos < entity_traits::to_entity(null), "No entities available");
- return entity_traits::combine(static_cast<typename entity_traits::entity_type>(pos), {});
- }
- auto recycle_identifier() ENTT_NOEXCEPT {
- ENTT_ASSERT(free_list != null, "No entities available");
- const auto curr = entity_traits::to_entity(free_list);
- free_list = entity_traits::combine(entity_traits::to_integral(entities[curr]), tombstone);
- return (entities[curr] = entity_traits::combine(curr, entity_traits::to_integral(entities[curr])));
- }
- auto release_entity(const Entity entity, const typename entity_traits::version_type version) {
- const typename entity_traits::version_type vers = version + (version == entity_traits::to_version(tombstone));
- entities[entity_traits::to_entity(entity)] = entity_traits::construct(entity_traits::to_integral(free_list), vers);
- free_list = entity_traits::combine(entity_traits::to_integral(entity), tombstone);
- return vers;
- }
- public:
- /*! @brief Underlying entity identifier. */
- using entity_type = Entity;
- /*! @brief Underlying version type. */
- using version_type = typename entity_traits::version_type;
- /*! @brief Unsigned integer type. */
- using size_type = std::size_t;
- /*! @brief Common type among all storage types. */
- using base_type = basic_common_type;
- /*! @brief Context type. */
- using context = internal::registry_context;
- /*! @brief Default constructor. */
- basic_registry()
- : pools{},
- groups{},
- entities{},
- free_list{tombstone},
- vars{} {}
- /**
- * @brief Allocates enough memory upon construction to store `count` pools.
- * @param count The number of pools to allocate memory for.
- */
- basic_registry(const size_type count)
- : pools{},
- groups{},
- entities{},
- free_list{tombstone},
- vars{} {
- pools.reserve(count);
- }
- /**
- * @brief Move constructor.
- * @param other The instance to move from.
- */
- basic_registry(basic_registry &&other)
- : pools{std::move(other.pools)},
- groups{std::move(other.groups)},
- entities{std::move(other.entities)},
- free_list{other.free_list},
- vars{std::move(other.vars)} {
- for(auto &&curr: pools) {
- curr.second->bind(forward_as_any(*this));
- }
- }
- /**
- * @brief Move assignment operator.
- * @param other The instance to move from.
- * @return This registry.
- */
- basic_registry &operator=(basic_registry &&other) {
- pools = std::move(other.pools);
- groups = std::move(other.groups);
- entities = std::move(other.entities);
- free_list = other.free_list;
- vars = std::move(other.vars);
- for(auto &&curr: pools) {
- curr.second->bind(forward_as_any(*this));
- }
- return *this;
- }
- /**
- * @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]] auto storage() ENTT_NOEXCEPT {
- return iterable_adaptor{internal::storage_proxy_iterator{pools.begin()}, internal::storage_proxy_iterator{pools.end()}};
- }
- /*! @copydoc storage */
- [[nodiscard]] auto storage() const ENTT_NOEXCEPT {
- return iterable_adaptor{internal::storage_proxy_iterator{pools.cbegin()}, internal::storage_proxy_iterator{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 An iterator to the given storage if it's found, past the end
- * iterator otherwise.
- */
- [[nodiscard]] auto storage(const id_type id) {
- return internal::storage_proxy_iterator{pools.find(id)};
- }
- /**
- * @brief Finds the storage associated with a given name, if any.
- * @param id Name used to map the storage within the registry.
- * @return An iterator to the given storage if it's found, past the end
- * iterator otherwise.
- */
- [[nodiscard]] auto storage(const id_type id) const {
- return internal::storage_proxy_iterator{pools.find(id)};
- }
- /**
- * @brief Returns the storage for a given component type.
- * @tparam Component Type of component of which to return the storage.
- * @param id Optional name used to map the storage within the registry.
- * @return The storage for the given component type.
- */
- template<typename Component>
- decltype(auto) storage(const id_type id = type_hash<std::remove_const_t<Component>>::value()) {
- if constexpr(std::is_const_v<Component>) {
- return std::as_const(*this).template storage<std::remove_const_t<Component>>(id);
- } else {
- return assure<Component>(id);
- }
- }
- /**
- * @brief Returns the storage for a given component type.
- *
- * @warning
- * If a storage for the given component doesn't exist yet, a temporary
- * placeholder is returned instead.
- *
- * @tparam Component Type of component of which to return the storage.
- * @param id Optional name used to map the storage within the registry.
- * @return The storage for the given component type.
- */
- template<typename Component>
- decltype(auto) storage(const id_type id = type_hash<std::remove_const_t<Component>>::value()) const {
- return assure<std::remove_const_t<Component>>(id);
- }
- /**
- * @brief Returns the number of entities created so far.
- * @return Number of entities created so far.
- */
- [[nodiscard]] size_type size() const ENTT_NOEXCEPT {
- return entities.size();
- }
- /**
- * @brief Returns the number of entities still in use.
- * @return Number of entities still in use.
- */
- [[nodiscard]] size_type alive() const {
- auto sz = entities.size();
- for(auto curr = free_list; curr != null; --sz) {
- curr = entities[entity_traits::to_entity(curr)];
- }
- return sz;
- }
- /**
- * @brief Increases the capacity (number of entities) of the registry.
- * @param cap Desired capacity.
- */
- void reserve(const size_type cap) {
- entities.reserve(cap);
- }
- /**
- * @brief Returns the number of entities that a registry has currently
- * allocated space for.
- * @return Capacity of the registry.
- */
- [[nodiscard]] size_type capacity() const ENTT_NOEXCEPT {
- return entities.capacity();
- }
- /**
- * @brief Checks whether the registry is empty (no entities still in use).
- * @return True if the registry is empty, false otherwise.
- */
- [[nodiscard]] bool empty() const {
- return !alive();
- }
- /**
- * @brief Direct access to the list of entities of a registry.
- *
- * The returned pointer is such that range `[data(), data() + size())` is
- * always a valid range, even if the registry is empty.
- *
- * @warning
- * This list contains both valid and destroyed entities and isn't suitable
- * for direct use.
- *
- * @return A pointer to the array of entities.
- */
- [[nodiscard]] const entity_type *data() const ENTT_NOEXCEPT {
- return entities.data();
- }
- /**
- * @brief Returns the head of the list of released entities.
- *
- * This function is intended for use in conjunction with `assign`.<br/>
- * The returned entity has an invalid identifier in all cases.
- *
- * @return The head of the list of released entities.
- */
- [[nodiscard]] entity_type released() const ENTT_NOEXCEPT {
- return free_list;
- }
- /**
- * @brief Checks if an identifier refers to a valid entity.
- * @param entity An identifier, either valid or not.
- * @return True if the identifier is valid, false otherwise.
- */
- [[nodiscard]] bool valid(const entity_type entity) const {
- const auto pos = size_type(entity_traits::to_entity(entity));
- return (pos < entities.size() && entities[pos] == entity);
- }
- /**
- * @brief Returns the actual version for an identifier.
- * @param entity A valid identifier.
- * @return The version for the given identifier if valid, the tombstone
- * version otherwise.
- */
- [[nodiscard]] version_type current(const entity_type entity) const {
- const auto pos = size_type(entity_traits::to_entity(entity));
- return entity_traits::to_version(pos < entities.size() ? entities[pos] : tombstone);
- }
- /**
- * @brief Creates a new entity or recycles a destroyed one.
- * @return A valid identifier.
- */
- [[nodiscard]] entity_type create() {
- return (free_list == null) ? entities.emplace_back(generate_identifier(entities.size())) : recycle_identifier();
- }
- /**
- * @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) {
- const auto length = entities.size();
- if(hint == null || hint == tombstone) {
- return create();
- } else if(const auto req = entity_traits::to_entity(hint); !(req < length)) {
- entities.resize(size_type(req) + 1u, null);
- for(auto pos = length; pos < req; ++pos) {
- release_entity(generate_identifier(pos), {});
- }
- return (entities[req] = hint);
- } else if(const auto curr = entity_traits::to_entity(entities[req]); req == curr) {
- return create();
- } else {
- auto *it = &free_list;
- for(; entity_traits::to_entity(*it) != req; it = &entities[entity_traits::to_entity(*it)]) {}
- *it = entity_traits::combine(curr, entity_traits::to_integral(*it));
- return (entities[req] = 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) {
- for(; free_list != null && first != last; ++first) {
- *first = recycle_identifier();
- }
- const auto length = entities.size();
- entities.resize(length + std::distance(first, last), null);
- for(auto pos = length; first != last; ++first, ++pos) {
- *first = entities[pos] = generate_identifier(pos);
- }
- }
- /**
- * @brief Assigns identifiers to an empty registry.
- *
- * This function is intended for use in conjunction with `data`, `size` and
- * `destroyed`.<br/>
- * Don't try to inject ranges of randomly generated entities nor the _wrong_
- * head for the list of destroyed entities. There is no guarantee that a
- * registry will continue to work properly in this case.
- *
- * @warning
- * There must be no entities still alive for this to work properly.
- *
- * @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 destroyed The head of the list of destroyed entities.
- */
- template<typename It>
- void assign(It first, It last, const entity_type destroyed) {
- ENTT_ASSERT(!alive(), "Entities still alive");
- entities.assign(first, last);
- free_list = destroyed;
- }
- /**
- * @brief Releases an identifier.
- *
- * The version is updated and the identifier can be recycled at any time.
- *
- * @warning
- * Attempting to use an invalid entity results in undefined behavior.
- *
- * @param entity A valid identifier.
- * @return The version of the recycled entity.
- */
- version_type release(const entity_type entity) {
- return release(entity, static_cast<version_type>(entity_traits::to_version(entity) + 1u));
- }
- /**
- * @brief Releases an identifier.
- *
- * The suggested version or the valid version closest to the suggested one
- * is used instead of the implicitly generated version.
- *
- * @sa release
- *
- * @param entity A valid identifier.
- * @param version A desired version upon destruction.
- * @return The version actually assigned to the entity.
- */
- version_type release(const entity_type entity, const version_type version) {
- ENTT_ASSERT(orphan(entity), "Non-orphan entity");
- return release_entity(entity, version);
- }
- /**
- * @brief Releases all identifiers in a range.
- *
- * @sa release
- *
- * @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 release(It first, It last) {
- for(; first != last; ++first) {
- release(*first);
- }
- }
- /**
- * @brief Destroys an entity and releases its identifier.
- *
- * @sa release
- *
- * @warning
- * Adding or removing components to an entity that is being destroyed can
- * result in undefined behavior. Attempting to use an invalid entity results
- * in undefined behavior.
- *
- * @param entity A valid identifier.
- * @return The version of the recycled entity.
- */
- version_type destroy(const entity_type entity) {
- return destroy(entity, static_cast<version_type>(entity_traits::to_version(entity) + 1u));
- }
- /**
- * @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 entity A valid identifier.
- * @param version A desired version upon destruction.
- * @return The version actually assigned to the entity.
- */
- version_type destroy(const entity_type entity, const version_type version) {
- ENTT_ASSERT(valid(entity), "Invalid entity");
- for(size_type pos = pools.size(); pos; --pos) {
- pools.begin()[pos - 1u].second->remove(entity);
- }
- return release_entity(entity, version);
- }
- /**
- * @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) {
- for(; first != last; ++first) {
- destroy(*first);
- }
- }
- /**
- * @brief Assigns the given component to an entity.
- *
- * The component must have a proper constructor or be of aggregate type.
- *
- * @warning
- * Attempting to use an invalid entity or to assign a component to an entity
- * that already owns it results in undefined behavior.
- *
- * @tparam Component Type of component to create.
- * @tparam Args Types of arguments to use to construct the component.
- * @param entity A valid identifier.
- * @param args Parameters to use to initialize the component.
- * @return A reference to the newly created component.
- */
- template<typename Component, typename... Args>
- decltype(auto) emplace(const entity_type entity, Args &&...args) {
- ENTT_ASSERT(valid(entity), "Invalid entity");
- return assure<Component>().emplace(entity, std::forward<Args>(args)...);
- }
- /**
- * @brief Assigns each entity in a range the given component.
- *
- * @sa emplace
- *
- * @tparam Component Type of component 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 component to assign.
- */
- template<typename Component, typename It>
- void insert(It first, It last, const Component &value = {}) {
- ENTT_ASSERT(std::all_of(first, last, [this](const auto entity) { return valid(entity); }), "Invalid entity");
- assure<Component>().insert(first, last, value);
- }
- /**
- * @brief Assigns each entity in a range the given components.
- *
- * @sa emplace
- *
- * @tparam Component Type of component 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 components.
- */
- template<typename Component, typename EIt, typename CIt, typename = std::enable_if_t<std::is_same_v<typename std::iterator_traits<CIt>::value_type, Component>>>
- void insert(EIt first, EIt last, CIt from) {
- ENTT_ASSERT(std::all_of(first, last, [this](const auto entity) { return valid(entity); }), "Invalid entity");
- assure<Component>().insert(first, last, from);
- }
- /**
- * @brief Assigns or replaces the given component for an entity.
- *
- * @warning
- * Attempting to use an invalid entity results in undefined behavior.
- *
- * @tparam Component Type of component to assign or replace.
- * @tparam Args Types of arguments to use to construct the component.
- * @param entity A valid identifier.
- * @param args Parameters to use to initialize the component.
- * @return A reference to the newly created component.
- */
- template<typename Component, typename... Args>
- decltype(auto) emplace_or_replace(const entity_type entity, Args &&...args) {
- ENTT_ASSERT(valid(entity), "Invalid entity");
- auto &cpool = assure<Component>();
- return cpool.contains(entity)
- ? cpool.patch(entity, [&args...](auto &...curr) { ((curr = Component{std::forward<Args>(args)...}), ...); })
- : cpool.emplace(entity, std::forward<Args>(args)...);
- }
- /**
- * @brief Patches the given component for an entity.
- *
- * The signature of the function should be equivalent to the following:
- *
- * @code{.cpp}
- * void(Component &);
- * @endcode
- *
- * @note
- * Empty types aren't explicitly instantiated and therefore they are never
- * returned. However, this function can be used to trigger an update signal
- * for them.
- *
- * @warning
- * Attempting to use an invalid entity or to patch a component of an entity
- * that doesn't own it results in undefined behavior.
- *
- * @tparam Component Type of component to patch.
- * @tparam Func Types of the function objects to invoke.
- * @param entity A valid identifier.
- * @param func Valid function objects.
- * @return A reference to the patched component.
- */
- template<typename Component, typename... Func>
- decltype(auto) patch(const entity_type entity, Func &&...func) {
- ENTT_ASSERT(valid(entity), "Invalid entity");
- return assure<Component>().patch(entity, std::forward<Func>(func)...);
- }
- /**
- * @brief Replaces the given component for an entity.
- *
- * The component must have a proper constructor or be of aggregate type.
- *
- * @warning
- * Attempting to use an invalid entity or to replace a component of an
- * entity that doesn't own it results in undefined behavior.
- *
- * @tparam Component Type of component to replace.
- * @tparam Args Types of arguments to use to construct the component.
- * @param entity A valid identifier.
- * @param args Parameters to use to initialize the component.
- * @return A reference to the component being replaced.
- */
- template<typename Component, typename... Args>
- decltype(auto) replace(const entity_type entity, Args &&...args) {
- ENTT_ASSERT(valid(entity), "Invalid entity");
- return assure<Component>().patch(entity, [&args...](auto &...curr) { ((curr = Component{std::forward<Args>(args)...}), ...); });
- }
- /**
- * @brief Removes the given components from an entity.
- *
- * @warning
- * Attempting to use an invalid entity results in undefined behavior.
- *
- * @tparam Component Type of component to remove.
- * @tparam Other Other types of components to remove.
- * @param entity A valid identifier.
- * @return The number of components actually removed.
- */
- template<typename Component, typename... Other>
- size_type remove(const entity_type entity) {
- ENTT_ASSERT(valid(entity), "Invalid entity");
- return (assure<Component>().remove(entity) + ... + assure<Other>().remove(entity));
- }
- /**
- * @brief Removes the given components from all the entities in a range.
- *
- * @sa remove
- *
- * @tparam Component Type of component to remove.
- * @tparam Other Other types of components 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 components actually removed.
- */
- template<typename Component, typename... Other, typename It>
- size_type remove(It first, It last) {
- if constexpr(sizeof...(Other) == 0u) {
- ENTT_ASSERT(std::all_of(first, last, [this](const auto entity) { return valid(entity); }), "Invalid entity");
- return assure<Component>().remove(std::move(first), std::move(last));
- } else {
- size_type count{};
- for(auto cpools = std::forward_as_tuple(assure<Component>(), assure<Other>()...); first != last; ++first) {
- ENTT_ASSERT(valid(*first), "Invalid entity");
- count += std::apply([entt = *first](auto &...curr) { return (curr.remove(entt) + ... + 0u); }, cpools);
- }
- return count;
- }
- }
- /**
- * @brief Erases the given components from an entity.
- *
- * @warning
- * Attempting to use an invalid entity or to erase a component from an
- * entity that doesn't own it results in undefined behavior.
- *
- * @tparam Component Types of components to erase.
- * @tparam Other Other types of components to erase.
- * @param entity A valid identifier.
- */
- template<typename Component, typename... Other>
- void erase(const entity_type entity) {
- ENTT_ASSERT(valid(entity), "Invalid entity");
- (assure<Component>().erase(entity), (assure<Other>().erase(entity), ...));
- }
- /**
- * @brief Erases the given components from all the entities in a range.
- *
- * @sa erase
- *
- * @tparam Component Types of components to erase.
- * @tparam Other Other types of components 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 Component, typename... Other, typename It>
- void erase(It first, It last) {
- if constexpr(sizeof...(Other) == 0u) {
- ENTT_ASSERT(std::all_of(first, last, [this](const auto entity) { return valid(entity); }), "Invalid entity");
- assure<Component>().erase(std::move(first), std::move(last));
- } else {
- for(auto cpools = std::forward_as_tuple(assure<Component>(), assure<Other>()...); first != last; ++first) {
- ENTT_ASSERT(valid(*first), "Invalid entity");
- std::apply([entt = *first](auto &...curr) { (curr.erase(entt), ...); }, cpools);
- }
- }
- }
- /**
- * @brief Removes all tombstones from a registry or only the pools for the
- * given components.
- * @tparam Component Types of components for which to clear all tombstones.
- */
- template<typename... Component>
- void compact() {
- if constexpr(sizeof...(Component) == 0) {
- for(auto &&curr: pools) {
- curr.second->compact();
- }
- } else {
- (assure<Component>().compact(), ...);
- }
- }
- /**
- * @brief Checks if an entity has all the given components.
- *
- * @warning
- * Attempting to use an invalid entity results in undefined behavior.
- *
- * @tparam Component Components for which to perform the check.
- * @param entity A valid identifier.
- * @return True if the entity has all the components, false otherwise.
- */
- template<typename... Component>
- [[nodiscard]] bool all_of(const entity_type entity) const {
- ENTT_ASSERT(valid(entity), "Invalid entity");
- return (assure<std::remove_const_t<Component>>().contains(entity) && ...);
- }
- /**
- * @brief Checks if an entity has at least one of the given components.
- *
- * @warning
- * Attempting to use an invalid entity results in undefined behavior.
- *
- * @tparam Component Components for which to perform the check.
- * @param entity A valid identifier.
- * @return True if the entity has at least one of the given components,
- * false otherwise.
- */
- template<typename... Component>
- [[nodiscard]] bool any_of(const entity_type entity) const {
- ENTT_ASSERT(valid(entity), "Invalid entity");
- return (assure<std::remove_const_t<Component>>().contains(entity) || ...);
- }
- /**
- * @brief Returns references to the given components for an entity.
- *
- * @warning
- * Attempting to use an invalid entity or to get a component from an entity
- * that doesn't own it results in undefined behavior.
- *
- * @tparam Component Types of components to get.
- * @param entity A valid identifier.
- * @return References to the components owned by the entity.
- */
- template<typename... Component>
- [[nodiscard]] decltype(auto) get([[maybe_unused]] const entity_type entity) const {
- ENTT_ASSERT(valid(entity), "Invalid entity");
- return view<Component...>().template get<const Component...>(entity);
- }
- /*! @copydoc get */
- template<typename... Component>
- [[nodiscard]] decltype(auto) get([[maybe_unused]] const entity_type entity) {
- ENTT_ASSERT(valid(entity), "Invalid entity");
- return view<Component...>().template get<Component...>(entity);
- }
- /**
- * @brief Returns a reference to the given component for an entity.
- *
- * In case the entity doesn't own the component, the parameters provided are
- * used to construct it.
- *
- * @warning
- * Attempting to use an invalid entity results in undefined behavior.
- *
- * @tparam Component Type of component to get.
- * @tparam Args Types of arguments to use to construct the component.
- * @param entity A valid identifier.
- * @param args Parameters to use to initialize the component.
- * @return Reference to the component owned by the entity.
- */
- template<typename Component, typename... Args>
- [[nodiscard]] decltype(auto) get_or_emplace(const entity_type entity, Args &&...args) {
- ENTT_ASSERT(valid(entity), "Invalid entity");
- auto &cpool = assure<Component>();
- return cpool.contains(entity) ? cpool.get(entity) : cpool.emplace(entity, std::forward<Args>(args)...);
- }
- /**
- * @brief Returns pointers to the given components for an entity.
- *
- * @warning
- * Attempting to use an invalid entity results in undefined behavior.
- *
- * @note
- * The registry retains ownership of the pointed-to components.
- *
- * @tparam Component Types of components to get.
- * @param entity A valid identifier.
- * @return Pointers to the components owned by the entity.
- */
- template<typename... Component>
- [[nodiscard]] auto try_get([[maybe_unused]] const entity_type entity) const {
- ENTT_ASSERT(valid(entity), "Invalid entity");
- if constexpr(sizeof...(Component) == 1) {
- const auto &cpool = assure<std::remove_const_t<Component>...>();
- return cpool.contains(entity) ? std::addressof(cpool.get(entity)) : nullptr;
- } else {
- return std::make_tuple(try_get<Component>(entity)...);
- }
- }
- /*! @copydoc try_get */
- template<typename... Component>
- [[nodiscard]] auto try_get([[maybe_unused]] const entity_type entity) {
- if constexpr(sizeof...(Component) == 1) {
- return (const_cast<Component *>(std::as_const(*this).template try_get<Component>(entity)), ...);
- } else {
- return std::make_tuple(try_get<Component>(entity)...);
- }
- }
- /**
- * @brief Clears a whole registry or the pools for the given components.
- * @tparam Component Types of components to remove from their entities.
- */
- template<typename... Component>
- void clear() {
- if constexpr(sizeof...(Component) == 0) {
- for(auto &&curr: pools) {
- curr.second->clear();
- }
- each([this](const auto entity) { this->release(entity); });
- } else {
- (assure<Component>().clear(), ...);
- }
- }
- /**
- * @brief Iterates all the entities that are still in use.
- *
- * The signature of the function should be equivalent to the following:
- *
- * @code{.cpp}
- * void(const Entity);
- * @endcode
- *
- * It's not defined whether entities created during iteration are returned.
- *
- * @tparam Func Type of the function object to invoke.
- * @param func A valid function object.
- */
- template<typename Func>
- void each(Func func) const {
- if(free_list == null) {
- for(auto pos = entities.size(); pos; --pos) {
- func(entities[pos - 1]);
- }
- } else {
- for(auto pos = entities.size(); pos; --pos) {
- if(const auto entity = entities[pos - 1]; entity_traits::to_entity(entity) == (pos - 1)) {
- func(entity);
- }
- }
- }
- }
- /**
- * @brief Checks if an entity has components assigned.
- * @param entity A valid identifier.
- * @return True if the entity has no components assigned, false otherwise.
- */
- [[nodiscard]] bool orphan(const entity_type entity) const {
- ENTT_ASSERT(valid(entity), "Invalid entity");
- return std::none_of(pools.cbegin(), pools.cend(), [entity](auto &&curr) { return curr.second->contains(entity); });
- }
- /**
- * @brief Returns a sink object for the given component.
- *
- * Use this function to receive notifications whenever a new instance of the
- * given component 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 component to the entity.
- *
- * @sa sink
- *
- * @tparam Component Type of component of which to get the sink.
- * @return A temporary sink object.
- */
- template<typename Component>
- [[nodiscard]] auto on_construct() {
- return assure<Component>().on_construct();
- }
- /**
- * @brief Returns a sink object for the given component.
- *
- * Use this function to receive notifications whenever an instance of the
- * given component 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 component.
- *
- * @sa sink
- *
- * @tparam Component Type of component of which to get the sink.
- * @return A temporary sink object.
- */
- template<typename Component>
- [[nodiscard]] auto on_update() {
- return assure<Component>().on_update();
- }
- /**
- * @brief Returns a sink object for the given component.
- *
- * Use this function to receive notifications whenever an instance of the
- * given component 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 component from the entity.
- *
- * @sa sink
- *
- * @tparam Component Type of component of which to get the sink.
- * @return A temporary sink object.
- */
- template<typename Component>
- [[nodiscard]] auto on_destroy() {
- return assure<Component>().on_destroy();
- }
- /**
- * @brief Returns a view for the given components.
- *
- * Views are created on the fly and share with the registry its internal
- * data structures. Feel free to discard them after the use.<br/>
- * Creating and destroying a view is an incredibly cheap operation. As a
- * rule of thumb, storing a view should never be an option.
- *
- * @tparam Component Type of component used to construct the view.
- * @tparam Other Other types of components used to construct the view.
- * @tparam Exclude Types of components used to filter the view.
- * @return A newly created view.
- */
- template<typename Component, typename... Other, typename... Exclude>
- [[nodiscard]] basic_view<entity_type, get_t<std::add_const_t<Component>, std::add_const_t<Other>...>, exclude_t<Exclude...>> view(exclude_t<Exclude...> = {}) const {
- return {assure<std::remove_const_t<Component>>(), assure<std::remove_const_t<Other>>()..., assure<Exclude>()...};
- }
- /*! @copydoc view */
- template<typename Component, typename... Other, typename... Exclude>
- [[nodiscard]] basic_view<entity_type, get_t<Component, Other...>, exclude_t<Exclude...>> view(exclude_t<Exclude...> = {}) {
- return {assure<std::remove_const_t<Component>>(), assure<std::remove_const_t<Other>>()..., assure<Exclude>()...};
- }
- /**
- * @brief Returns a group for the given components.
- *
- * Groups are created on the fly and share with the registry its internal
- * data structures. Feel free to discard them after the use.<br/>
- * Creating and destroying a group is an incredibly cheap operation. As a
- * rule of thumb, storing a group should never be an option.
- *
- * Groups support exclusion lists and can own types of components. The more
- * types are owned by a group, the faster it is to iterate entities and
- * components.<br/>
- * However, groups also affect some features of the registry such as the
- * creation and destruction of components.
- *
- * @note
- * Pools of components that are owned by a group cannot be sorted anymore.
- * The group takes the ownership of the pools and arrange components so as
- * to iterate them as fast as possible.
- *
- * @tparam Owned Types of components owned by the group.
- * @tparam Get Types of components observed by the group.
- * @tparam Exclude Types of components used to filter the group.
- * @return A newly created group.
- */
- template<typename... Owned, typename... Get, typename... Exclude>
- [[nodiscard]] basic_group<entity_type, owned_t<Owned...>, get_t<Get...>, exclude_t<Exclude...>> group(get_t<Get...>, exclude_t<Exclude...> = {}) {
- static_assert(sizeof...(Owned) + sizeof...(Get) > 0, "Exclusion-only groups are not supported");
- static_assert(sizeof...(Owned) + sizeof...(Get) + sizeof...(Exclude) > 1, "Single component groups are not allowed");
- using handler_type = group_handler<exclude_t<std::remove_const_t<Exclude>...>, get_t<std::remove_const_t<Get>...>, std::remove_const_t<Owned>...>;
- const auto cpools = std::forward_as_tuple(assure<std::remove_const_t<Owned>>()..., assure<std::remove_const_t<Get>>()...);
- constexpr auto size = sizeof...(Owned) + sizeof...(Get) + sizeof...(Exclude);
- handler_type *handler = nullptr;
- auto it = std::find_if(groups.cbegin(), groups.cend(), [size](const auto &gdata) {
- return gdata.size == size
- && (gdata.owned(type_hash<std::remove_const_t<Owned>>::value()) && ...)
- && (gdata.get(type_hash<std::remove_const_t<Get>>::value()) && ...)
- && (gdata.exclude(type_hash<Exclude>::value()) && ...);
- });
- if(it != groups.cend()) {
- handler = static_cast<handler_type *>(it->group.get());
- } else {
- group_data candidate = {
- size,
- {new handler_type{}, [](void *instance) { delete static_cast<handler_type *>(instance); }},
- []([[maybe_unused]] const id_type ctype) ENTT_NOEXCEPT { return ((ctype == type_hash<std::remove_const_t<Owned>>::value()) || ...); },
- []([[maybe_unused]] const id_type ctype) ENTT_NOEXCEPT { return ((ctype == type_hash<std::remove_const_t<Get>>::value()) || ...); },
- []([[maybe_unused]] const id_type ctype) ENTT_NOEXCEPT { return ((ctype == type_hash<Exclude>::value()) || ...); },
- };
- handler = static_cast<handler_type *>(candidate.group.get());
- const void *maybe_valid_if = nullptr;
- const void *discard_if = nullptr;
- if constexpr(sizeof...(Owned) == 0) {
- groups.push_back(std::move(candidate));
- } else {
- [[maybe_unused]] auto has_conflict = [size](const auto &gdata) {
- const auto overlapping = (0u + ... + gdata.owned(type_hash<std::remove_const_t<Owned>>::value()));
- const auto sz = overlapping + (0u + ... + gdata.get(type_hash<std::remove_const_t<Get>>::value())) + (0u + ... + gdata.exclude(type_hash<Exclude>::value()));
- return !overlapping || ((sz == size) || (sz == gdata.size));
- };
- ENTT_ASSERT(std::all_of(groups.cbegin(), groups.cend(), std::move(has_conflict)), "Conflicting groups");
- const auto next = std::find_if_not(groups.cbegin(), groups.cend(), [size](const auto &gdata) {
- return !(0u + ... + gdata.owned(type_hash<std::remove_const_t<Owned>>::value())) || (size > gdata.size);
- });
- const auto prev = std::find_if(std::make_reverse_iterator(next), groups.crend(), [](const auto &gdata) {
- return (0u + ... + gdata.owned(type_hash<std::remove_const_t<Owned>>::value()));
- });
- maybe_valid_if = (next == groups.cend() ? maybe_valid_if : next->group.get());
- discard_if = (prev == groups.crend() ? discard_if : prev->group.get());
- groups.insert(next, std::move(candidate));
- }
- (on_construct<std::remove_const_t<Owned>>().before(maybe_valid_if).template connect<&handler_type::template maybe_valid_if<std::remove_const_t<Owned>>>(*handler), ...);
- (on_construct<std::remove_const_t<Get>>().before(maybe_valid_if).template connect<&handler_type::template maybe_valid_if<std::remove_const_t<Get>>>(*handler), ...);
- (on_destroy<Exclude>().before(maybe_valid_if).template connect<&handler_type::template maybe_valid_if<Exclude>>(*handler), ...);
- (on_destroy<std::remove_const_t<Owned>>().before(discard_if).template connect<&handler_type::discard_if>(*handler), ...);
- (on_destroy<std::remove_const_t<Get>>().before(discard_if).template connect<&handler_type::discard_if>(*handler), ...);
- (on_construct<Exclude>().before(discard_if).template connect<&handler_type::discard_if>(*handler), ...);
- if constexpr(sizeof...(Owned) == 0) {
- for(const auto entity: view<Owned..., Get...>(exclude<Exclude...>)) {
- handler->current.emplace(entity);
- }
- } else {
- // we cannot iterate backwards because we want to leave behind valid entities in case of owned types
- for(auto *first = std::get<0>(cpools).data(), *last = first + std::get<0>(cpools).size(); first != last; ++first) {
- handler->template maybe_valid_if<type_list_element_t<0, type_list<std::remove_const_t<Owned>...>>>(*this, *first);
- }
- }
- }
- return {handler->current, std::get<storage_type<std::remove_const_t<Owned>> &>(cpools)..., std::get<storage_type<std::remove_const_t<Get>> &>(cpools)...};
- }
- /*! @copydoc group */
- template<typename... Owned, typename... Get, typename... Exclude>
- [[nodiscard]] basic_group<entity_type, owned_t<std::add_const_t<Owned>...>, get_t<std::add_const_t<Get>...>, exclude_t<Exclude...>> group_if_exists(get_t<Get...>, exclude_t<Exclude...> = {}) const {
- auto it = std::find_if(groups.cbegin(), groups.cend(), [](const auto &gdata) {
- return gdata.size == (sizeof...(Owned) + sizeof...(Get) + sizeof...(Exclude))
- && (gdata.owned(type_hash<std::remove_const_t<Owned>>::value()) && ...)
- && (gdata.get(type_hash<std::remove_const_t<Get>>::value()) && ...)
- && (gdata.exclude(type_hash<Exclude>::value()) && ...);
- });
- if(it == groups.cend()) {
- return {};
- } else {
- using handler_type = group_handler<exclude_t<std::remove_const_t<Exclude>...>, get_t<std::remove_const_t<Get>...>, std::remove_const_t<Owned>...>;
- return {static_cast<handler_type *>(it->group.get())->current, assure<std::remove_const_t<Owned>>()..., assure<std::remove_const_t<Get>>()...};
- }
- }
- /*! @copydoc group */
- template<typename... Owned, typename... Exclude>
- [[nodiscard]] basic_group<entity_type, owned_t<Owned...>, get_t<>, exclude_t<Exclude...>> group(exclude_t<Exclude...> = {}) {
- return group<Owned...>(get_t<>{}, exclude<Exclude...>);
- }
- /*! @copydoc group */
- template<typename... Owned, typename... Exclude>
- [[nodiscard]] basic_group<entity_type, owned_t<std::add_const_t<Owned>...>, get_t<>, exclude_t<Exclude...>> group_if_exists(exclude_t<Exclude...> = {}) const {
- return group_if_exists<std::add_const_t<Owned>...>(get_t<>{}, exclude<Exclude...>);
- }
- /**
- * @brief Checks whether the given components belong to any group.
- * @tparam Component Types of components in which one is interested.
- * @return True if the pools of the given components are _free_, false
- * otherwise.
- */
- template<typename... Component>
- [[nodiscard]] bool owned() const {
- return std::any_of(groups.cbegin(), groups.cend(), [](auto &&gdata) { return (gdata.owned(type_hash<std::remove_const_t<Component>>::value()) || ...); });
- }
- /**
- * @brief Checks whether a group can be sorted.
- * @tparam Owned Types of components owned by the group.
- * @tparam Get Types of components observed by the group.
- * @tparam Exclude Types of components used to filter the group.
- * @return True if the group can be sorted, false otherwise.
- */
- template<typename... Owned, typename... Get, typename... Exclude>
- [[nodiscard]] bool sortable(const basic_group<entity_type, owned_t<Owned...>, get_t<Get...>, exclude_t<Exclude...>> &) ENTT_NOEXCEPT {
- constexpr auto size = sizeof...(Owned) + sizeof...(Get) + sizeof...(Exclude);
- auto pred = [size](const auto &gdata) { return (0u + ... + gdata.owned(type_hash<std::remove_const_t<Owned>>::value())) && (size < gdata.size); };
- return std::find_if(groups.cbegin(), groups.cend(), std::move(pred)) == groups.cend();
- }
- /**
- * @brief Sorts the elements of a given component.
- *
- * The order remains valid until a component of the given type is assigned
- * to or removed from an entity.<br/>
- * 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 Component &, const Component &);
- * @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 components owned by a group cannot be sorted.
- *
- * @tparam Component Type of components 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 Component, typename Compare, typename Sort = std_sort, typename... Args>
- void sort(Compare compare, Sort algo = Sort{}, Args &&...args) {
- ENTT_ASSERT(!owned<Component>(), "Cannot sort owned storage");
- auto &cpool = assure<Component>();
- 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 components in the same way.
- *
- * Being `To` and `From` the two sets, after invoking this function an
- * iterator for `To` returns elements according to the following rules:
- *
- * * All entities in `To` that are also in `From` are returned first
- * according to the order they have in `From`.
- * * All entities in `To` that are not in `From` are returned in no
- * particular order after all the other entities.
- *
- * Any subsequent change to `From` won't affect the order in `To`.
- *
- * @warning
- * Pools of components owned by a group cannot be sorted.
- *
- * @tparam To Type of components to sort.
- * @tparam From Type of components to use to sort.
- */
- template<typename To, typename From>
- void sort() {
- ENTT_ASSERT(!owned<To>(), "Cannot sort owned storage");
- assure<To>().respect(assure<From>());
- }
- /**
- * @brief Returns the context object, that is, a general purpose container.
- * @return The context object, that is, a general purpose container.
- */
- context &ctx() ENTT_NOEXCEPT {
- return vars;
- }
- /*! @copydoc ctx */
- const context &ctx() const ENTT_NOEXCEPT {
- return vars;
- }
- private:
- dense_map<id_type, std::unique_ptr<base_type>, identity> pools;
- std::vector<group_data> groups;
- std::vector<entity_type> entities;
- entity_type free_list;
- context vars;
- };
- } // namespace entt
- #endif
- // #include "entity/runtime_view.hpp"
- #ifndef ENTT_ENTITY_RUNTIME_VIEW_HPP
- #define ENTT_ENTITY_RUNTIME_VIEW_HPP
- #include <algorithm>
- #include <iterator>
- #include <type_traits>
- #include <utility>
- #include <vector>
- // #include "../config/config.h"
- // #include "entity.hpp"
- // #include "fwd.hpp"
- // #include "sparse_set.hpp"
- namespace entt {
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- namespace internal {
- template<typename Set>
- class runtime_view_iterator final {
- using iterator_type = typename Set::iterator;
- [[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 difference_type = typename iterator_type::difference_type;
- using value_type = typename iterator_type::value_type;
- using pointer = typename iterator_type::pointer;
- using reference = typename iterator_type::reference;
- using iterator_category = std::bidirectional_iterator_tag;
- runtime_view_iterator() ENTT_NOEXCEPT
- : pools{},
- filter{},
- it{},
- tombstone_check{} {}
- runtime_view_iterator(const std::vector<const Set *> &cpools, const std::vector<const Set *> &ignore, iterator_type curr) ENTT_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++() {
- while(++it != (*pools)[0]->end() && !valid()) {}
- return *this;
- }
- runtime_view_iterator operator++(int) {
- runtime_view_iterator orig = *this;
- return ++(*this), orig;
- }
- runtime_view_iterator &operator--() {
- while(--it != (*pools)[0]->begin() && !valid()) {}
- return *this;
- }
- runtime_view_iterator operator--(int) {
- runtime_view_iterator orig = *this;
- return operator--(), orig;
- }
- [[nodiscard]] pointer operator->() const ENTT_NOEXCEPT {
- return it.operator->();
- }
- [[nodiscard]] reference operator*() const ENTT_NOEXCEPT {
- return *operator->();
- }
- [[nodiscard]] bool operator==(const runtime_view_iterator &other) const ENTT_NOEXCEPT {
- return it == other.it;
- }
- [[nodiscard]] bool operator!=(const runtime_view_iterator &other) const ENTT_NOEXCEPT {
- return !(*this == other);
- }
- private:
- const std::vector<const Set *> *pools;
- const std::vector<const Set *> *filter;
- iterator_type it;
- bool tombstone_check;
- };
- } // namespace internal
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /**
- * @brief Runtime view implementation.
- *
- * Primary template isn't defined on purpose. All the specializations give a
- * compile-time error, but for a few reasonable cases.
- */
- template<typename>
- struct basic_runtime_view;
- /**
- * @brief Generic runtime view.
- *
- * Runtime views iterate over those entities that have at least all the given
- * components in their bags. During initialization, a runtime view looks at the
- * number of entities available for each component and picks up a reference to
- * the smallest set of candidate entities in order to get a performance boost
- * when iterate.<br/>
- * Order of elements during iterations are highly dependent on the order of the
- * underlying data structures. See sparse_set and its specializations for more
- * details.
- *
- * @b Important
- *
- * Iterators aren't invalidated if:
- *
- * * New instances of the given components are created and assigned to entities.
- * * The entity currently pointed is modified (as an example, if one of the
- * given components is removed from the entity to which the iterator points).
- * * The entity currently pointed is destroyed.
- *
- * In all the other cases, modifying the pools of the given components in any
- * way invalidates all the iterators and using them results in undefined
- * behavior.
- *
- * @note
- * Views share references to the underlying data structures of the registry that
- * generated them. Therefore any change to the entities and to the components
- * made by means of the registry are immediately reflected by the views, unless
- * a pool was missing when the view was built (in this case, the view won't
- * have a valid reference and won't be updated accordingly).
- *
- * @warning
- * Lifetime of a view must not overcome that of the registry that generated it.
- * In any other case, attempting to use a view results in undefined behavior.
- *
- * @tparam Entity A valid entity type (see entt_traits for more details).
- * @tparam Allocator Type of allocator used to manage memory and elements.
- */
- template<typename Entity, typename Allocator>
- struct basic_runtime_view<basic_sparse_set<Entity, Allocator>> {
- /*! @brief Underlying entity identifier. */
- using entity_type = Entity;
- /*! @brief Unsigned integer type. */
- using size_type = std::size_t;
- /*! @brief Common type among all storage types. */
- using base_type = basic_sparse_set<Entity, Allocator>;
- /*! @brief Bidirectional iterator type. */
- using iterator = internal::runtime_view_iterator<base_type>;
- /*! @brief Default constructor to use to create empty, invalid views. */
- basic_runtime_view() ENTT_NOEXCEPT
- : pools{},
- filter{} {}
- /**
- * @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(const base_type &base) {
- if(pools.empty() || !(base.size() < pools[0u]->size())) {
- pools.push_back(&base);
- } else {
- pools.push_back(std::exchange(pools[0u], &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(const base_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{} : pools.front()->size();
- }
- /**
- * @brief Returns an iterator to the first entity that has the given
- * components.
- *
- * The returned iterator points to the first entity that has the given
- * components. If the view is empty, the returned iterator will be equal to
- * `end()`.
- *
- * @return An iterator to the first entity that has the given components.
- */
- [[nodiscard]] iterator begin() const {
- return pools.empty() ? iterator{} : iterator{pools, filter, pools[0]->begin()};
- }
- /**
- * @brief Returns an iterator that is past the last entity that has the
- * given components.
- *
- * The returned iterator points to the entity following the last entity that
- * has the given components. Attempting to dereference the returned iterator
- * results in undefined behavior.
- *
- * @return An iterator to the entity following the last entity that has the
- * given components.
- */
- [[nodiscard]] iterator end() const {
- return pools.empty() ? iterator{} : iterator{pools, filter, pools[0]->end()};
- }
- /**
- * @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); });
- }
- /**
- * @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. To get the components, users can use the registry with
- * which the view was built.<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:
- std::vector<const base_type *> pools;
- std::vector<const base_type *> filter;
- };
- } // namespace entt
- #endif
- // #include "entity/sigh_storage_mixin.hpp"
- #ifndef ENTT_ENTITY_SIGH_STORAGE_MIXIN_HPP
- #define ENTT_ENTITY_SIGH_STORAGE_MIXIN_HPP
- #include <utility>
- // #include "../config/config.h"
- // #include "../core/any.hpp"
- // #include "../signal/sigh.hpp"
- // #include "fwd.hpp"
- namespace entt {
- /**
- * @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 The type of the underlying storage.
- */
- template<typename Type>
- class sigh_storage_mixin final: public Type {
- using basic_iterator = typename Type::basic_iterator;
- template<typename Func>
- void notify_destruction(basic_iterator first, basic_iterator last, Func func) {
- ENTT_ASSERT(owner != nullptr, "Invalid pointer to registry");
- for(; first != last; ++first) {
- const auto entt = *first;
- destruction.publish(*owner, entt);
- const auto it = Type::find(entt);
- func(it, it + 1u);
- }
- }
- void swap_and_pop(basic_iterator first, basic_iterator last) final {
- notify_destruction(std::move(first), std::move(last), [this](auto... args) { Type::swap_and_pop(args...); });
- }
- void in_place_pop(basic_iterator first, basic_iterator last) final {
- notify_destruction(std::move(first), std::move(last), [this](auto... args) { Type::in_place_pop(args...); });
- }
- basic_iterator try_emplace(const typename Type::entity_type entt, const bool force_back, const void *value) final {
- ENTT_ASSERT(owner != nullptr, "Invalid pointer to registry");
- Type::try_emplace(entt, force_back, value);
- construction.publish(*owner, entt);
- return Type::find(entt);
- }
- public:
- /*! @brief Underlying entity identifier. */
- using entity_type = typename Type::entity_type;
- /*! @brief Inherited constructors. */
- using Type::Type;
- /**
- * @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() ENTT_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() ENTT_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() ENTT_NOEXCEPT {
- return sink{destruction};
- }
- /**
- * @brief Assigns entities to a storage.
- * @tparam Args Types of arguments to use to construct the object.
- * @param entt A valid identifier.
- * @param args Parameters to use to initialize the object.
- * @return A reference to the newly created object.
- */
- template<typename... Args>
- decltype(auto) emplace(const entity_type entt, Args &&...args) {
- ENTT_ASSERT(owner != nullptr, "Invalid pointer to registry");
- Type::emplace(entt, std::forward<Args>(args)...);
- construction.publish(*owner, entt);
- return this->get(entt);
- }
- /**
- * @brief Patches the given instance for an entity.
- * @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) {
- ENTT_ASSERT(owner != nullptr, "Invalid pointer to registry");
- Type::patch(entt, std::forward<Func>(func)...);
- update.publish(*owner, entt);
- return this->get(entt);
- }
- /**
- * @brief Assigns entities to a storage.
- * @tparam It Type of input iterator.
- * @tparam Args Types of arguments to use to construct the objects assigned
- * to the entities.
- * @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 initialize the objects assigned to the
- * entities.
- */
- template<typename It, typename... Args>
- void insert(It first, It last, Args &&...args) {
- ENTT_ASSERT(owner != nullptr, "Invalid pointer to registry");
- Type::insert(first, last, std::forward<Args>(args)...);
- for(auto it = construction.empty() ? last : first; it != last; ++it) {
- construction.publish(*owner, *it);
- }
- }
- /**
- * @brief Forwards variables to mixins, if any.
- * @param value A variable wrapped in an opaque container.
- */
- void bind(any value) ENTT_NOEXCEPT final {
- auto *reg = any_cast<basic_registry<entity_type>>(&value);
- owner = reg ? reg : owner;
- Type::bind(std::move(value));
- }
- private:
- sigh<void(basic_registry<entity_type> &, const entity_type)> construction{};
- sigh<void(basic_registry<entity_type> &, const entity_type)> destruction{};
- sigh<void(basic_registry<entity_type> &, const entity_type)> update{};
- basic_registry<entity_type> *owner{};
- };
- } // namespace entt
- #endif
- // #include "entity/snapshot.hpp"
- #ifndef ENTT_ENTITY_SNAPSHOT_HPP
- #define ENTT_ENTITY_SNAPSHOT_HPP
- #include <array>
- #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 "component.hpp"
- // #include "entity.hpp"
- // #include "fwd.hpp"
- // #include "registry.hpp"
- namespace entt {
- /**
- * @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 components of interest.<br/>
- * This type can be used in both cases if provided with a correctly configured
- * output archive.
- *
- * @tparam Entity A valid entity type (see entt_traits for more details).
- */
- template<typename Entity>
- class basic_snapshot {
- using entity_traits = entt_traits<Entity>;
- template<typename Component, typename Archive, typename It>
- void get(Archive &archive, std::size_t sz, It first, It last) const {
- const auto view = reg->template view<std::add_const_t<Component>>();
- archive(typename entity_traits::entity_type(sz));
- while(first != last) {
- const auto entt = *(first++);
- if(reg->template all_of<Component>(entt)) {
- std::apply(archive, std::tuple_cat(std::make_tuple(entt), view.get(entt)));
- }
- }
- }
- template<typename... Component, typename Archive, typename It, std::size_t... Index>
- void component(Archive &archive, It first, It last, std::index_sequence<Index...>) const {
- std::array<std::size_t, sizeof...(Index)> size{};
- auto begin = first;
- while(begin != last) {
- const auto entt = *(begin++);
- ((reg->template all_of<Component>(entt) ? ++size[Index] : 0u), ...);
- }
- (get<Component>(archive, size[Index], first, last), ...);
- }
- public:
- /*! @brief Underlying entity identifier. */
- using entity_type = Entity;
- /**
- * @brief Constructs an instance that is bound to a given registry.
- * @param source A valid reference to a registry.
- */
- basic_snapshot(const basic_registry<entity_type> &source) ENTT_NOEXCEPT
- : reg{&source} {}
- /*! @brief Default move constructor. */
- basic_snapshot(basic_snapshot &&) ENTT_NOEXCEPT = default;
- /*! @brief Default move assignment operator. @return This snapshot. */
- basic_snapshot &operator=(basic_snapshot &&) ENTT_NOEXCEPT = default;
- /**
- * @brief Puts aside all the entities from the underlying registry.
- *
- * Entities are serialized along with their versions. Destroyed entities are
- * taken in consideration as well by this function.
- *
- * @tparam Archive Type of output archive.
- * @param archive A valid reference to an output archive.
- * @return An object of this type to continue creating the snapshot.
- */
- template<typename Archive>
- const basic_snapshot &entities(Archive &archive) const {
- const auto sz = reg->size();
- archive(typename entity_traits::entity_type(sz + 1u));
- archive(reg->released());
- for(auto first = reg->data(), last = first + sz; first != last; ++first) {
- archive(*first);
- }
- return *this;
- }
- /**
- * @brief Puts aside the given components.
- *
- * Each instance is serialized together with the entity to which it belongs.
- * Entities are serialized along with their versions.
- *
- * @tparam Component Types of components to serialize.
- * @tparam Archive Type of output archive.
- * @param archive A valid reference to an output archive.
- * @return An object of this type to continue creating the snapshot.
- */
- template<typename... Component, typename Archive>
- const basic_snapshot &component(Archive &archive) const {
- if constexpr(sizeof...(Component) == 1u) {
- const auto view = reg->template view<const Component...>();
- (component<Component>(archive, view.rbegin(), view.rend()), ...);
- return *this;
- } else {
- (component<Component>(archive), ...);
- return *this;
- }
- }
- /**
- * @brief Puts aside the given components for the entities in a range.
- *
- * Each instance is serialized together with the entity to which it belongs.
- * Entities are serialized along with their versions.
- *
- * @tparam Component Types of components 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.
- * @return An object of this type to continue creating the snapshot.
- */
- template<typename... Component, typename Archive, typename It>
- const basic_snapshot &component(Archive &archive, It first, It last) const {
- component<Component...>(archive, first, last, std::index_sequence_for<Component...>{});
- return *this;
- }
- private:
- const basic_registry<entity_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 Entity A valid entity type (see entt_traits for more details).
- */
- template<typename Entity>
- class basic_snapshot_loader {
- using entity_traits = entt_traits<Entity>;
- template<typename Type, typename Archive>
- void assign(Archive &archive) const {
- typename entity_traits::entity_type length{};
- entity_type entt;
- archive(length);
- if constexpr(ignore_as_empty_v<Type>) {
- while(length--) {
- archive(entt);
- const auto entity = reg->valid(entt) ? entt : reg->create(entt);
- ENTT_ASSERT(entity == entt, "Entity not available for use");
- reg->template emplace<Type>(entt);
- }
- } else {
- Type instance;
- while(length--) {
- archive(entt, instance);
- const auto entity = reg->valid(entt) ? entt : reg->create(entt);
- ENTT_ASSERT(entity == entt, "Entity not available for use");
- reg->template emplace<Type>(entt, std::move(instance));
- }
- }
- }
- public:
- /*! @brief Underlying entity identifier. */
- using entity_type = Entity;
- /**
- * @brief Constructs an instance that is bound to a given registry.
- * @param source A valid reference to a registry.
- */
- basic_snapshot_loader(basic_registry<entity_type> &source) ENTT_NOEXCEPT
- : reg{&source} {
- // restoring a snapshot as a whole requires a clean registry
- ENTT_ASSERT(reg->empty(), "Registry must be empty");
- }
- /*! @brief Default move constructor. */
- basic_snapshot_loader(basic_snapshot_loader &&) ENTT_NOEXCEPT = default;
- /*! @brief Default move assignment operator. @return This loader. */
- basic_snapshot_loader &operator=(basic_snapshot_loader &&) ENTT_NOEXCEPT = default;
- /**
- * @brief Restores entities that were in use during serialization.
- *
- * This function restores the entities that were in use during serialization
- * and gives them the versions they originally had.
- *
- * @tparam Archive Type of input archive.
- * @param archive A valid reference to an input archive.
- * @return A valid loader to continue restoring data.
- */
- template<typename Archive>
- const basic_snapshot_loader &entities(Archive &archive) const {
- typename entity_traits::entity_type length{};
- archive(length);
- std::vector<entity_type> all(length);
- for(std::size_t pos{}; pos < length; ++pos) {
- archive(all[pos]);
- }
- reg->assign(++all.cbegin(), all.cend(), all[0u]);
- return *this;
- }
- /**
- * @brief Restores components and assigns them to the right entities.
- *
- * The template parameter list must be exactly the same used during
- * serialization. In the event that the entity to which the component is
- * assigned doesn't exist yet, the loader will take care to create it with
- * the version it originally had.
- *
- * @tparam Component Types of components to restore.
- * @tparam Archive Type of input archive.
- * @param archive A valid reference to an input archive.
- * @return A valid loader to continue restoring data.
- */
- template<typename... Component, typename Archive>
- const basic_snapshot_loader &component(Archive &archive) const {
- (assign<Component>(archive), ...);
- return *this;
- }
- /**
- * @brief Destroys those entities that have no components.
- *
- * In case all the entities were serialized but only part of the components
- * was saved, it could happen that some of the entities have no components
- * once restored.<br/>
- * This functions helps to identify and destroy those entities.
- *
- * @return A valid loader to continue restoring data.
- */
- const basic_snapshot_loader &orphans() const {
- reg->each([this](const auto entt) {
- if(reg->orphan(entt)) {
- reg->release(entt);
- }
- });
- return *this;
- }
- private:
- basic_registry<entity_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 applications with
- * the requirement of transferring somehow parts of the representation side to
- * side.
- *
- * @tparam Entity A valid entity type (see entt_traits for more details).
- */
- template<typename Entity>
- class basic_continuous_loader {
- using entity_traits = entt_traits<Entity>;
- void destroy(Entity entt) {
- if(const auto it = remloc.find(entt); it == remloc.cend()) {
- const auto local = reg->create();
- remloc.emplace(entt, std::make_pair(local, true));
- reg->destroy(local);
- }
- }
- void restore(Entity entt) {
- const auto it = remloc.find(entt);
- if(it == remloc.cend()) {
- const auto local = reg->create();
- remloc.emplace(entt, std::make_pair(local, true));
- } else {
- if(!reg->valid(remloc[entt].first)) {
- remloc[entt].first = reg->create();
- }
- // set the dirty flag
- remloc[entt].second = true;
- }
- }
- 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 Other, typename Type, typename Member>
- void update([[maybe_unused]] Other &instance, [[maybe_unused]] Member Type::*member) {
- if constexpr(!std::is_same_v<Other, Type>) {
- 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);
- }
- }
- template<typename Component>
- void remove_if_exists() {
- for(auto &&ref: remloc) {
- const auto local = ref.second.first;
- if(reg->valid(local)) {
- reg->template remove<Component>(local);
- }
- }
- }
- template<typename Other, typename Archive, typename... Type, typename... Member>
- void assign(Archive &archive, [[maybe_unused]] Member Type::*...member) {
- typename entity_traits::entity_type length{};
- entity_type entt;
- archive(length);
- if constexpr(ignore_as_empty_v<Other>) {
- while(length--) {
- archive(entt);
- restore(entt);
- reg->template emplace_or_replace<Other>(map(entt));
- }
- } else {
- Other instance;
- while(length--) {
- archive(entt, instance);
- (update(instance, member), ...);
- restore(entt);
- reg->template emplace_or_replace<Other>(map(entt), std::move(instance));
- }
- }
- }
- public:
- /*! @brief Underlying entity identifier. */
- using entity_type = Entity;
- /**
- * @brief Constructs an instance that is bound to a given registry.
- * @param source A valid reference to a registry.
- */
- basic_continuous_loader(basic_registry<entity_type> &source) ENTT_NOEXCEPT
- : reg{&source} {}
- /*! @brief Default move constructor. */
- basic_continuous_loader(basic_continuous_loader &&) = default;
- /*! @brief Default move assignment operator. @return This loader. */
- basic_continuous_loader &operator=(basic_continuous_loader &&) = default;
- /**
- * @brief Restores entities that were in use during serialization.
- *
- * This function restores the entities that were in use during serialization
- * and creates local counterparts for them if required.
- *
- * @tparam Archive Type of input archive.
- * @param archive A valid reference to an input archive.
- * @return A non-const reference to this loader.
- */
- template<typename Archive>
- basic_continuous_loader &entities(Archive &archive) {
- typename entity_traits::entity_type length{};
- entity_type entt{};
- archive(length);
- // discards the head of the list of destroyed entities
- archive(entt);
- for(std::size_t pos{}, last = length - 1u; pos < last; ++pos) {
- archive(entt);
- if(const auto entity = entity_traits::to_entity(entt); entity == pos) {
- restore(entt);
- } else {
- destroy(entt);
- }
- }
- return *this;
- }
- /**
- * @brief Restores components and assigns them to the right entities.
- *
- * The template parameter list must be exactly the same used during
- * serialization. In the event that the entity to which the component is
- * assigned doesn't exist yet, the loader will take care to create a local
- * counterpart for it.<br/>
- * Members can be either data members of type entity_type or containers of
- * entities. In both cases, the loader will visit them and update the
- * entities by replacing each one with its local counterpart.
- *
- * @tparam Component Type of component to restore.
- * @tparam Archive Type of input archive.
- * @tparam Type Types of components to update with local counterparts.
- * @tparam Member Types of members to update with their local counterparts.
- * @param archive A valid reference to an input archive.
- * @param member Members to update with their local counterparts.
- * @return A non-const reference to this loader.
- */
- template<typename... Component, typename Archive, typename... Type, typename... Member>
- basic_continuous_loader &component(Archive &archive, Member Type::*...member) {
- (remove_if_exists<Component>(), ...);
- (assign<Component>(archive, member...), ...);
- return *this;
- }
- /**
- * @brief Helps to purge entities that no longer have a conterpart.
- *
- * Users should invoke this member function after restoring each snapshot,
- * unless they know exactly what they are doing.
- *
- * @return A non-const reference to this loader.
- */
- basic_continuous_loader &shrink() {
- auto it = remloc.begin();
- while(it != remloc.cend()) {
- const auto local = it->second.first;
- bool &dirty = it->second.second;
- if(dirty) {
- dirty = false;
- ++it;
- } else {
- if(reg->valid(local)) {
- reg->destroy(local);
- }
- it = remloc.erase(it);
- }
- }
- return *this;
- }
- /**
- * @brief Destroys those entities that have no components.
- *
- * In case all the entities were serialized but only part of the components
- * was saved, it could happen that some of the entities have no components
- * once restored.<br/>
- * This functions helps to identify and destroy those entities.
- *
- * @return A non-const reference to this loader.
- */
- basic_continuous_loader &orphans() {
- reg->each([this](const auto entt) {
- if(reg->orphan(entt)) {
- reg->release(entt);
- }
- });
- 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 ENTT_NOEXCEPT {
- return (remloc.find(entt) != remloc.cend());
- }
- /**
- * @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 ENTT_NOEXCEPT {
- const auto it = remloc.find(entt);
- entity_type other = null;
- if(it != remloc.cend()) {
- other = it->second.first;
- }
- return other;
- }
- private:
- dense_map<entity_type, std::pair<entity_type, bool>> remloc;
- basic_registry<entity_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/memory.hpp"
- // #include "../core/type_info.hpp"
- // #include "entity.hpp"
- // #include "fwd.hpp"
- namespace entt {
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- 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;
- sparse_set_iterator() ENTT_NOEXCEPT
- : packed{},
- offset{} {}
- sparse_set_iterator(const Container &ref, const difference_type idx) ENTT_NOEXCEPT
- : packed{std::addressof(ref)},
- offset{idx} {}
- sparse_set_iterator &operator++() ENTT_NOEXCEPT {
- return --offset, *this;
- }
- sparse_set_iterator operator++(int) ENTT_NOEXCEPT {
- sparse_set_iterator orig = *this;
- return ++(*this), orig;
- }
- sparse_set_iterator &operator--() ENTT_NOEXCEPT {
- return ++offset, *this;
- }
- sparse_set_iterator operator--(int) ENTT_NOEXCEPT {
- sparse_set_iterator orig = *this;
- return operator--(), orig;
- }
- sparse_set_iterator &operator+=(const difference_type value) ENTT_NOEXCEPT {
- offset -= value;
- return *this;
- }
- sparse_set_iterator operator+(const difference_type value) const ENTT_NOEXCEPT {
- sparse_set_iterator copy = *this;
- return (copy += value);
- }
- sparse_set_iterator &operator-=(const difference_type value) ENTT_NOEXCEPT {
- return (*this += -value);
- }
- sparse_set_iterator operator-(const difference_type value) const ENTT_NOEXCEPT {
- return (*this + -value);
- }
- [[nodiscard]] reference operator[](const difference_type value) const ENTT_NOEXCEPT {
- return packed->data()[index() - value];
- }
- [[nodiscard]] pointer operator->() const ENTT_NOEXCEPT {
- return packed->data() + index();
- }
- [[nodiscard]] reference operator*() const ENTT_NOEXCEPT {
- return *operator->();
- }
- [[nodiscard]] difference_type index() const ENTT_NOEXCEPT {
- return offset - 1;
- }
- private:
- const Container *packed;
- difference_type offset;
- };
- template<typename Type, typename Other>
- [[nodiscard]] std::ptrdiff_t operator-(const sparse_set_iterator<Type> &lhs, const sparse_set_iterator<Other> &rhs) ENTT_NOEXCEPT {
- return rhs.index() - lhs.index();
- }
- template<typename Type, typename Other>
- [[nodiscard]] bool operator==(const sparse_set_iterator<Type> &lhs, const sparse_set_iterator<Other> &rhs) ENTT_NOEXCEPT {
- return lhs.index() == rhs.index();
- }
- template<typename Type, typename Other>
- [[nodiscard]] bool operator!=(const sparse_set_iterator<Type> &lhs, const sparse_set_iterator<Other> &rhs) ENTT_NOEXCEPT {
- return !(lhs == rhs);
- }
- template<typename Type, typename Other>
- [[nodiscard]] bool operator<(const sparse_set_iterator<Type> &lhs, const sparse_set_iterator<Other> &rhs) ENTT_NOEXCEPT {
- return lhs.index() > rhs.index();
- }
- template<typename Type, typename Other>
- [[nodiscard]] bool operator>(const sparse_set_iterator<Type> &lhs, const sparse_set_iterator<Other> &rhs) ENTT_NOEXCEPT {
- return lhs.index() < rhs.index();
- }
- template<typename Type, typename Other>
- [[nodiscard]] bool operator<=(const sparse_set_iterator<Type> &lhs, const sparse_set_iterator<Other> &rhs) ENTT_NOEXCEPT {
- return !(lhs > rhs);
- }
- template<typename Type, typename Other>
- [[nodiscard]] bool operator>=(const sparse_set_iterator<Type> &lhs, const sparse_set_iterator<Other> &rhs) ENTT_NOEXCEPT {
- return !(lhs < rhs);
- }
- } // namespace internal
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /*! @brief Sparse set 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 Basic 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 is largely used by the registry to offer users the fastest access ever
- * to the components. Views and groups in general are almost entirely designed
- * around sparse sets.
- *
- * 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 (see entt_traits for more details).
- * @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 entity_traits = entt_traits<Entity>;
- [[nodiscard]] auto sparse_ptr(const Entity entt) const {
- const auto pos = static_cast<size_type>(entity_traits::to_entity(entt));
- const auto page = pos / entity_traits::page_size;
- return (page < sparse.size() && sparse[page]) ? (sparse[page] + fast_mod(pos, entity_traits::page_size)) : nullptr;
- }
- [[nodiscard]] auto &sparse_ref(const Entity entt) const {
- ENTT_ASSERT(sparse_ptr(entt), "Invalid element");
- const auto pos = static_cast<size_type>(entity_traits::to_entity(entt));
- return sparse[pos / entity_traits::page_size][fast_mod(pos, entity_traits::page_size)];
- }
- [[nodiscard]] auto &assure_at_least(const Entity entt) {
- const auto pos = static_cast<size_type>(entity_traits::to_entity(entt));
- const auto page = pos / entity_traits::page_size;
- if(!(page < sparse.size())) {
- sparse.resize(page + 1u, nullptr);
- }
- if(!sparse[page]) {
- auto page_allocator{packed.get_allocator()};
- sparse[page] = alloc_traits::allocate(page_allocator, entity_traits::page_size);
- std::uninitialized_fill(sparse[page], sparse[page] + entity_traits::page_size, null);
- }
- auto &elem = sparse[page][fast_mod(pos, entity_traits::page_size)];
- ENTT_ASSERT(entity_traits::to_version(elem) == entity_traits::to_version(tombstone), "Slot not available");
- return elem;
- }
- void release_sparse_pages() {
- auto page_allocator{packed.get_allocator()};
- for(auto &&page: sparse) {
- if(page != nullptr) {
- std::destroy(page, page + entity_traits::page_size);
- alloc_traits::deallocate(page_allocator, page, entity_traits::page_size);
- page = nullptr;
- }
- }
- }
- private:
- virtual const void *get_at(const std::size_t) const {
- return nullptr;
- }
- virtual void swap_at(const std::size_t, const std::size_t) {}
- virtual void move_element(const std::size_t, const std::size_t) {}
- protected:
- /*! @brief Random access iterator type. */
- using basic_iterator = internal::sparse_set_iterator<packed_container_type>;
- /**
- * @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 swap_and_pop(basic_iterator first, basic_iterator last) {
- for(; first != last; ++first) {
- auto &self = sparse_ref(*first);
- const auto entt = entity_traits::to_entity(self);
- sparse_ref(packed.back()) = entity_traits::combine(entt, entity_traits::to_integral(packed.back()));
- packed[static_cast<size_type>(entt)] = packed.back();
- // unnecessary but it helps to detect nasty bugs
- ENTT_ASSERT((packed.back() = tombstone, true), "");
- // lazy self-assignment guard
- self = null;
- packed.pop_back();
- }
- }
- /**
- * @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 in_place_pop(basic_iterator first, basic_iterator last) {
- for(; first != last; ++first) {
- const auto entt = entity_traits::to_entity(std::exchange(sparse_ref(*first), null));
- packed[static_cast<size_type>(entt)] = std::exchange(free_list, entity_traits::combine(entt, entity_traits::reserved));
- }
- }
- /**
- * @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(!contains(entt), "Set already contains entity");
- if(auto &elem = assure_at_least(entt); free_list == null || force_back) {
- packed.push_back(entt);
- elem = entity_traits::combine(static_cast<typename entity_traits::entity_type>(packed.size() - 1u), entity_traits::to_integral(entt));
- return begin();
- } else {
- const auto pos = static_cast<size_type>(entity_traits::to_entity(free_list));
- elem = entity_traits::combine(entity_traits::to_integral(free_list), entity_traits::to_integral(entt));
- free_list = std::exchange(packed[pos], entt);
- return --(end() - pos);
- }
- }
- public:
- /*! @brief Allocator type. */
- using allocator_type = Allocator;
- /*! @brief Underlying entity identifier. */
- using entity_type = Entity;
- /*! @brief Underlying version type. */
- using version_type = typename entity_traits::version_type;
- /*! @brief Unsigned integer type. */
- using size_type = typename packed_container_type::size_type;
- /*! @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 = reverse_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{type_id<void>(), 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 value 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 &value, deletion_policy pol = deletion_policy::swap_and_pop, const allocator_type &allocator = {})
- : sparse{allocator},
- packed{allocator},
- info{&value},
- free_list{tombstone},
- mode{pol} {}
- /**
- * @brief Move constructor.
- * @param other The instance to move from.
- */
- basic_sparse_set(basic_sparse_set &&other) ENTT_NOEXCEPT
- : sparse{std::move(other.sparse)},
- packed{std::move(other.packed)},
- info{other.info},
- free_list{std::exchange(other.free_list, tombstone)},
- mode{other.mode} {}
- /**
- * @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) ENTT_NOEXCEPT
- : sparse{std::move(other.sparse), allocator},
- packed{std::move(other.packed), allocator},
- info{other.info},
- free_list{std::exchange(other.free_list, tombstone)},
- mode{other.mode} {
- ENTT_ASSERT(alloc_traits::is_always_equal::value || packed.get_allocator() == other.packed.get_allocator(), "Copying a sparse set is not allowed");
- }
- /*! @brief Default destructor. */
- virtual ~basic_sparse_set() {
- release_sparse_pages();
- }
- /**
- * @brief Move assignment operator.
- * @param other The instance to move from.
- * @return This sparse set.
- */
- basic_sparse_set &operator=(basic_sparse_set &&other) ENTT_NOEXCEPT {
- ENTT_ASSERT(alloc_traits::is_always_equal::value || packed.get_allocator() == other.packed.get_allocator(), "Copying a sparse set is not allowed");
- release_sparse_pages();
- sparse = std::move(other.sparse);
- packed = std::move(other.packed);
- info = other.info;
- free_list = std::exchange(other.free_list, tombstone);
- mode = other.mode;
- 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) {
- using std::swap;
- swap(sparse, other.sparse);
- swap(packed, other.packed);
- swap(info, other.info);
- swap(free_list, other.free_list);
- swap(mode, other.mode);
- }
- /**
- * @brief Returns the associated allocator.
- * @return The associated allocator.
- */
- [[nodiscard]] constexpr allocator_type get_allocator() const ENTT_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 ENTT_NOEXCEPT {
- return mode;
- }
- /**
- * @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 ENTT_NOEXCEPT {
- return packed.capacity();
- }
- /*! @brief Requests the removal of unused capacity. */
- virtual void 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 the internal packed 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 Extent of the sparse set.
- */
- [[nodiscard]] size_type extent() const ENTT_NOEXCEPT {
- return sparse.size() * entity_traits::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 ENTT_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 ENTT_NOEXCEPT {
- return packed.empty();
- }
- /**
- * @brief Direct access to the internal packed array.
- * @return A pointer to the internal packed array.
- */
- [[nodiscard]] pointer data() const ENTT_NOEXCEPT {
- return packed.data();
- }
- /**
- * @brief Returns an iterator to the beginning.
- *
- * The returned iterator points to the first entity of the internal packed
- * array. 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]] const_iterator begin() const ENTT_NOEXCEPT {
- const auto pos = static_cast<typename iterator::difference_type>(packed.size());
- return iterator{packed, pos};
- }
- /*! @copydoc begin */
- [[nodiscard]] const_iterator cbegin() const ENTT_NOEXCEPT {
- return begin();
- }
- /**
- * @brief Returns an iterator to the end.
- *
- * The returned iterator points to the element following the last entity in
- * a sparse set. Attempting to dereference the returned iterator results in
- * undefined behavior.
- *
- * @return An iterator to the element following the last entity of a sparse
- * set.
- */
- [[nodiscard]] iterator end() const ENTT_NOEXCEPT {
- return iterator{packed, {}};
- }
- /*! @copydoc end */
- [[nodiscard]] const_iterator cend() const ENTT_NOEXCEPT {
- return end();
- }
- /**
- * @brief Returns a reverse iterator to the beginning.
- *
- * The returned iterator points to the first entity of the reversed internal
- * packed array. 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]] const_reverse_iterator rbegin() const ENTT_NOEXCEPT {
- return std::make_reverse_iterator(end());
- }
- /*! @copydoc rbegin */
- [[nodiscard]] const_reverse_iterator crbegin() const ENTT_NOEXCEPT {
- return rbegin();
- }
- /**
- * @brief Returns a reverse iterator to the end.
- *
- * The returned iterator points to the element following the last entity in
- * the reversed sparse set. Attempting to dereference the returned iterator
- * results in undefined behavior.
- *
- * @return An iterator to the element following the last entity of the
- * reversed sparse set.
- */
- [[nodiscard]] reverse_iterator rend() const ENTT_NOEXCEPT {
- return std::make_reverse_iterator(begin());
- }
- /*! @copydoc rend */
- [[nodiscard]] const_reverse_iterator crend() const ENTT_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]] iterator find(const entity_type entt) const ENTT_NOEXCEPT {
- return contains(entt) ? --(end() - index(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 ENTT_NOEXCEPT {
- const auto elem = sparse_ptr(entt);
- constexpr auto cap = entity_traits::to_entity(null);
- // testing versions permits to avoid accessing the packed array
- return elem && (((~cap & entity_traits::to_integral(entt)) ^ entity_traits::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 ENTT_NOEXCEPT {
- const auto elem = sparse_ptr(entt);
- constexpr auto fallback = entity_traits::to_version(tombstone);
- return elem ? entity_traits::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 ENTT_NOEXCEPT {
- ENTT_ASSERT(contains(entt), "Set does not contain entity");
- return static_cast<size_type>(entity_traits::to_entity(sparse_ref(entt)));
- }
- /**
- * @brief Returns the entity at specified location, with bounds checking.
- * @param pos The position for which to return the entity.
- * @return The entity at specified location if any, a null entity otherwise.
- */
- [[nodiscard]] entity_type at(const size_type pos) const ENTT_NOEXCEPT {
- return pos < packed.size() ? packed[pos] : null;
- }
- /**
- * @brief Returns the entity at specified location, without bounds checking.
- * @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 ENTT_NOEXCEPT {
- ENTT_ASSERT(pos < packed.size(), "Position is 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.
- */
- const void *get(const entity_type entt) const ENTT_NOEXCEPT {
- return get_at(index(entt));
- }
- /*! @copydoc get */
- void *get(const entity_type entt) ENTT_NOEXCEPT {
- return const_cast<void *>(std::as_const(*this).get(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 value Optional opaque value to forward to mixins, if any.
- * @return Iterator pointing to the emplaced element in case of success, the
- * `end()` iterator otherwise.
- */
- iterator emplace(const entity_type entt, const void *value = nullptr) {
- return try_emplace(entt, false, value);
- }
- /**
- * @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.
- */
- void bump(const entity_type entt) {
- auto &entity = sparse_ref(entt);
- entity = entity_traits::combine(entity_traits::to_integral(entity), entity_traits::to_integral(entt));
- packed[static_cast<size_type>(entity_traits::to_entity(entity))] = entt;
- }
- /**
- * @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 insert(It first, It last) {
- for(auto it = first; it != last; ++it) {
- try_emplace(*it, true);
- }
- return first == last ? end() : find(*first);
- }
- /**
- * @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 = --(end() - index(entt));
- (mode == deletion_policy::in_place) ? in_place_pop(it, it + 1u) : swap_and_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>) {
- (mode == deletion_policy::in_place) ? in_place_pop(first, last) : swap_and_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{};
- for(; first != last; ++first) {
- count += remove(*first);
- }
- return count;
- }
- /*! @brief Removes all tombstones from the packed array of a sparse set. */
- void compact() {
- size_type from = packed.size();
- for(; from && packed[from - 1u] == tombstone; --from) {}
- for(auto *it = &free_list; *it != null && from; it = std::addressof(packed[entity_traits::to_entity(*it)])) {
- if(const size_type to = entity_traits::to_entity(*it); to < from) {
- --from;
- move_element(from, to);
- using std::swap;
- swap(packed[from], packed[to]);
- const auto entity = static_cast<typename entity_traits::entity_type>(to);
- sparse_ref(packed[to]) = entity_traits::combine(entity, entity_traits::to_integral(packed[to]));
- *it = entity_traits::combine(static_cast<typename entity_traits::entity_type>(from), entity_traits::reserved);
- for(; from && packed[from - 1u] == tombstone; --from) {}
- }
- }
- free_list = tombstone;
- packed.resize(from);
- }
- /**
- * @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) {
- ENTT_ASSERT(contains(lhs) && contains(rhs), "Set does not contain entities");
- auto &entt = sparse_ref(lhs);
- auto &other = sparse_ref(rhs);
- const auto from = entity_traits::to_entity(entt);
- const auto to = entity_traits::to_entity(other);
- // basic no-leak guarantee (with invalid state) if swapping throws
- swap_at(static_cast<size_type>(from), static_cast<size_type>(to));
- entt = entity_traits::combine(to, entity_traits::to_integral(packed[from]));
- other = entity_traits::combine(from, entity_traits::to_integral(packed[to]));
- using std::swap;
- swap(packed[from], packed[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(!(length > packed.size()), "Length exceeds the number of elements");
- ENTT_ASSERT(free_list == null, "Partial sorting with tombstones is not supported");
- algo(packed.rend() - 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_at(next, idx);
- const auto entity = static_cast<typename entity_traits::entity_type>(curr);
- sparse_ref(entt) = entity_traits::combine(entity, entity_traits::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) {
- compact();
- sort_n(packed.size(), std::move(compare), std::move(algo), std::forward<Args>(args)...);
- }
- /**
- * @brief Sort entities according to their order in another sparse set.
- *
- * Entities that are part of both the sparse sets are ordered internally
- * according to the order they have in `other`. All the other entities goes
- * to the end of the list and there are no guarantees on their order.<br/>
- * In other terms, this function can be used to impose the same order on two
- * sets by using one of them as a master and the other one as a slave.
- *
- * Iterating the sparse set with a couple of iterators returns elements in
- * the expected order after a call to `respect`. See `begin` and `end` for
- * more details.
- *
- * @param other The sparse sets that imposes the order of the entities.
- */
- void respect(const basic_sparse_set &other) {
- compact();
- const auto to = other.end();
- auto from = other.begin();
- for(size_type pos = packed.size() - 1; pos && from != to; ++from) {
- if(contains(*from)) {
- if(*from != packed[pos]) {
- // basic no-leak guarantee (with invalid state) if swapping throws
- swap_elements(packed[pos], *from);
- }
- --pos;
- }
- }
- }
- /*! @brief Clears a sparse set. */
- void clear() {
- if(const auto last = end(); free_list == null) {
- in_place_pop(begin(), last);
- } else {
- for(auto &&entity: *this) {
- // tombstone filter on itself
- if(const auto it = find(entity); it != last) {
- in_place_pop(it, it + 1u);
- }
- }
- }
- free_list = tombstone;
- packed.clear();
- }
- /**
- * @brief Returned value type, if any.
- * @return Returned value type, if any.
- */
- const type_info &type() const ENTT_NOEXCEPT {
- return *info;
- }
- /*! @brief Forwards variables to mixins, if any. */
- virtual void bind(any) ENTT_NOEXCEPT {}
- private:
- sparse_container_type sparse;
- packed_container_type packed;
- const type_info *info;
- entity_type free_list;
- deletion_policy mode;
- };
- } // 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/compressed_pair.hpp"
- // #include "../core/iterator.hpp"
- // #include "../core/memory.hpp"
- // #include "../core/type_info.hpp"
- // #include "component.hpp"
- // #include "entity.hpp"
- // #include "fwd.hpp"
- // #include "sigh_storage_mixin.hpp"
- // #include "sparse_set.hpp"
- namespace entt {
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- namespace internal {
- template<typename Container>
- class storage_iterator final {
- friend storage_iterator<const Container>;
- using container_type = std::remove_const_t<Container>;
- using alloc_traits = std::allocator_traits<typename container_type::allocator_type>;
- using comp_traits = component_traits<typename container_type::value_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;
- storage_iterator() ENTT_NOEXCEPT = default;
- storage_iterator(Container *ref, difference_type idx) ENTT_NOEXCEPT
- : packed{ref},
- offset{idx} {}
- template<bool Const = std::is_const_v<Container>, typename = std::enable_if_t<Const>>
- storage_iterator(const storage_iterator<std::remove_const_t<Container>> &other) ENTT_NOEXCEPT
- : packed{other.packed},
- offset{other.offset} {}
- storage_iterator &operator++() ENTT_NOEXCEPT {
- return --offset, *this;
- }
- storage_iterator operator++(int) ENTT_NOEXCEPT {
- storage_iterator orig = *this;
- return ++(*this), orig;
- }
- storage_iterator &operator--() ENTT_NOEXCEPT {
- return ++offset, *this;
- }
- storage_iterator operator--(int) ENTT_NOEXCEPT {
- storage_iterator orig = *this;
- return operator--(), orig;
- }
- storage_iterator &operator+=(const difference_type value) ENTT_NOEXCEPT {
- offset -= value;
- return *this;
- }
- storage_iterator operator+(const difference_type value) const ENTT_NOEXCEPT {
- storage_iterator copy = *this;
- return (copy += value);
- }
- storage_iterator &operator-=(const difference_type value) ENTT_NOEXCEPT {
- return (*this += -value);
- }
- storage_iterator operator-(const difference_type value) const ENTT_NOEXCEPT {
- return (*this + -value);
- }
- [[nodiscard]] reference operator[](const difference_type value) const ENTT_NOEXCEPT {
- const auto pos = index() - value;
- return (*packed)[pos / comp_traits::page_size][fast_mod(pos, comp_traits::page_size)];
- }
- [[nodiscard]] pointer operator->() const ENTT_NOEXCEPT {
- const auto pos = index();
- return (*packed)[pos / comp_traits::page_size] + fast_mod(pos, comp_traits::page_size);
- }
- [[nodiscard]] reference operator*() const ENTT_NOEXCEPT {
- return *operator->();
- }
- [[nodiscard]] difference_type index() const ENTT_NOEXCEPT {
- return offset - 1;
- }
- private:
- Container *packed;
- difference_type offset;
- };
- template<typename CLhs, typename CRhs>
- [[nodiscard]] std::ptrdiff_t operator-(const storage_iterator<CLhs> &lhs, const storage_iterator<CRhs> &rhs) ENTT_NOEXCEPT {
- return rhs.index() - lhs.index();
- }
- template<typename CLhs, typename CRhs>
- [[nodiscard]] bool operator==(const storage_iterator<CLhs> &lhs, const storage_iterator<CRhs> &rhs) ENTT_NOEXCEPT {
- return lhs.index() == rhs.index();
- }
- template<typename CLhs, typename CRhs>
- [[nodiscard]] bool operator!=(const storage_iterator<CLhs> &lhs, const storage_iterator<CRhs> &rhs) ENTT_NOEXCEPT {
- return !(lhs == rhs);
- }
- template<typename CLhs, typename CRhs>
- [[nodiscard]] bool operator<(const storage_iterator<CLhs> &lhs, const storage_iterator<CRhs> &rhs) ENTT_NOEXCEPT {
- return lhs.index() > rhs.index();
- }
- template<typename CLhs, typename CRhs>
- [[nodiscard]] bool operator>(const storage_iterator<CLhs> &lhs, const storage_iterator<CRhs> &rhs) ENTT_NOEXCEPT {
- return lhs.index() < rhs.index();
- }
- template<typename CLhs, typename CRhs>
- [[nodiscard]] bool operator<=(const storage_iterator<CLhs> &lhs, const storage_iterator<CRhs> &rhs) ENTT_NOEXCEPT {
- return !(lhs > rhs);
- }
- template<typename CLhs, typename CRhs>
- [[nodiscard]] bool operator>=(const storage_iterator<CLhs> &lhs, const storage_iterator<CRhs> &rhs) ENTT_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 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;
- extended_storage_iterator() = default;
- extended_storage_iterator(It 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> && ...)>>
- extended_storage_iterator(const extended_storage_iterator<It, Args...> &other)
- : it{other.it} {}
- extended_storage_iterator &operator++() ENTT_NOEXCEPT {
- return ++std::get<It>(it), (++std::get<Other>(it), ...), *this;
- }
- extended_storage_iterator operator++(int) ENTT_NOEXCEPT {
- extended_storage_iterator orig = *this;
- return ++(*this), orig;
- }
- [[nodiscard]] pointer operator->() const ENTT_NOEXCEPT {
- return operator*();
- }
- [[nodiscard]] reference operator*() const ENTT_NOEXCEPT {
- return {*std::get<It>(it), *std::get<Other>(it)...};
- }
- template<typename... CLhs, typename... CRhs>
- friend bool operator==(const extended_storage_iterator<CLhs...> &, const extended_storage_iterator<CRhs...> &) ENTT_NOEXCEPT;
- private:
- std::tuple<It, Other...> it;
- };
- template<typename... CLhs, typename... CRhs>
- [[nodiscard]] bool operator==(const extended_storage_iterator<CLhs...> &lhs, const extended_storage_iterator<CRhs...> &rhs) ENTT_NOEXCEPT {
- return std::get<0>(lhs.it) == std::get<0>(rhs.it);
- }
- template<typename... CLhs, typename... CRhs>
- [[nodiscard]] bool operator!=(const extended_storage_iterator<CLhs...> &lhs, const extended_storage_iterator<CRhs...> &rhs) ENTT_NOEXCEPT {
- return !(lhs == rhs);
- }
- } // namespace internal
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /**
- * @brief Basic 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 Entity A valid entity type (see entt_traits for more details).
- * @tparam Type Type of objects assigned to the entities.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- */
- template<typename Entity, typename Type, typename Allocator, typename>
- class basic_storage: public basic_sparse_set<Entity, typename std::allocator_traits<Allocator>::template rebind_alloc<Entity>> {
- static_assert(std::is_move_constructible_v<Type> && std::is_move_assignable_v<Type>, "The type must be at least move constructible/assignable");
- using alloc_traits = std::allocator_traits<Allocator>;
- static_assert(std::is_same_v<typename alloc_traits::value_type, Type>, "Invalid value type");
- using underlying_type = basic_sparse_set<Entity, typename alloc_traits::template rebind_alloc<Entity>>;
- using container_type = std::vector<typename alloc_traits::pointer, typename alloc_traits::template rebind_alloc<typename alloc_traits::pointer>>;
- using comp_traits = component_traits<Type>;
- [[nodiscard]] auto &element_at(const std::size_t pos) const {
- return packed.first()[pos / comp_traits::page_size][fast_mod(pos, comp_traits::page_size)];
- }
- auto assure_at_least(const std::size_t pos) {
- auto &&container = packed.first();
- const auto idx = pos / comp_traits::page_size;
- if(!(idx < container.size())) {
- auto curr = container.size();
- container.resize(idx + 1u, nullptr);
- ENTT_TRY {
- for(const auto last = container.size(); curr < last; ++curr) {
- container[curr] = alloc_traits::allocate(packed.second(), comp_traits::page_size);
- }
- }
- ENTT_CATCH {
- container.resize(curr);
- ENTT_THROW;
- }
- }
- return container[idx] + fast_mod(pos, comp_traits::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 = assure_at_least(static_cast<size_type>(it.index()));
- entt::uninitialized_construct_using_allocator(to_address(elem), packed.second(), std::forward<Args>(args)...);
- }
- ENTT_CATCH {
- if constexpr(comp_traits::in_place_delete) {
- base_type::in_place_pop(it, it + 1u);
- } else {
- base_type::swap_and_pop(it, it + 1u);
- }
- ENTT_THROW;
- }
- return it;
- }
- void shrink_to_size(const std::size_t sz) {
- for(auto pos = sz, length = base_type::size(); pos < length; ++pos) {
- if constexpr(comp_traits::in_place_delete) {
- if(base_type::at(pos) != tombstone) {
- std::destroy_at(std::addressof(element_at(pos)));
- }
- } else {
- std::destroy_at(std::addressof(element_at(pos)));
- }
- }
- auto &&container = packed.first();
- auto page_allocator{packed.second()};
- const auto from = (sz + comp_traits::page_size - 1u) / comp_traits::page_size;
- for(auto pos = from, last = container.size(); pos < last; ++pos) {
- alloc_traits::deallocate(page_allocator, container[pos], comp_traits::page_size);
- }
- container.resize(from);
- }
- private:
- const void *get_at(const std::size_t pos) const final {
- return std::addressof(element_at(pos));
- }
- void swap_at(const std::size_t lhs, const std::size_t rhs) final {
- using std::swap;
- swap(element_at(lhs), element_at(rhs));
- }
- void move_element(const std::size_t from, const std::size_t to) final {
- auto &elem = element_at(from);
- entt::uninitialized_construct_using_allocator(to_address(assure_at_least(to)), packed.second(), std::move(elem));
- std::destroy_at(std::addressof(elem));
- }
- protected:
- /**
- * @brief Erases elements from a storage.
- * @param first An iterator to the first element to erase.
- * @param last An iterator past the last element to erase.
- */
- void swap_and_pop(typename underlying_type::basic_iterator first, typename underlying_type::basic_iterator last) override {
- for(; first != last; ++first) {
- // cannot use first::index() because it would break with cross iterators
- const auto pos = base_type::index(*first);
- auto &elem = element_at(base_type::size() - 1u);
- // destroying on exit allows reentrant destructors
- [[maybe_unused]] auto unused = std::exchange(element_at(pos), std::move(elem));
- std::destroy_at(std::addressof(elem));
- base_type::swap_and_pop(first, first + 1u);
- }
- }
- /**
- * @brief Erases elements from a storage.
- * @param first An iterator to the first element to erase.
- * @param last An iterator past the last element to erase.
- */
- void in_place_pop(typename underlying_type::basic_iterator first, typename underlying_type::basic_iterator last) override {
- for(; first != last; ++first) {
- // cannot use first::index() because it would break with cross iterators
- const auto pos = base_type::index(*first);
- base_type::in_place_pop(first, first + 1u);
- std::destroy_at(std::addressof(element_at(pos)));
- }
- }
- /**
- * @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.
- */
- typename underlying_type::basic_iterator try_emplace([[maybe_unused]] const Entity entt, const bool force_back, const void *value) override {
- if(value) {
- if constexpr(std::is_copy_constructible_v<value_type>) {
- return emplace_element(entt, force_back, *static_cast<const value_type *>(value));
- } else {
- return base_type::end();
- }
- } else {
- if constexpr(std::is_default_constructible_v<value_type>) {
- return emplace_element(entt, force_back);
- } else {
- return base_type::end();
- }
- }
- }
- public:
- /*! @brief Base type. */
- using base_type = underlying_type;
- /*! @brief Allocator type. */
- using allocator_type = Allocator;
- /*! @brief Type of the objects assigned to entities. */
- using value_type = Type;
- /*! @brief Underlying entity identifier. */
- using entity_type = Entity;
- /*! @brief Unsigned integer type. */
- using size_type = std::size_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>;
- /*! @brief Constant random access iterator type. */
- using const_iterator = internal::storage_iterator<const container_type>;
- /*! @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 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<value_type>(), deletion_policy{comp_traits::in_place_delete}, allocator},
- packed{container_type{allocator}, allocator} {}
- /**
- * @brief Move constructor.
- * @param other The instance to move from.
- */
- basic_storage(basic_storage &&other) ENTT_NOEXCEPT
- : base_type{std::move(other)},
- packed{std::move(other.packed)} {}
- /**
- * @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) ENTT_NOEXCEPT
- : base_type{std::move(other), allocator},
- packed{container_type{std::move(other.packed.first()), allocator}, allocator} {
- ENTT_ASSERT(alloc_traits::is_always_equal::value || packed.second() == other.packed.second(), "Copying a storage is not allowed");
- }
- /*! @brief Default destructor. */
- ~basic_storage() override {
- shrink_to_size(0u);
- }
- /**
- * @brief Move assignment operator.
- * @param other The instance to move from.
- * @return This storage.
- */
- basic_storage &operator=(basic_storage &&other) ENTT_NOEXCEPT {
- ENTT_ASSERT(alloc_traits::is_always_equal::value || packed.second() == other.packed.second(), "Copying a storage is not allowed");
- shrink_to_size(0u);
- base_type::operator=(std::move(other));
- packed.first() = std::move(other.packed.first());
- propagate_on_container_move_assignment(packed.second(), other.packed.second());
- 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) {
- using std::swap;
- underlying_type::swap(other);
- propagate_on_container_swap(packed.second(), other.packed.second());
- swap(packed.first(), other.packed.first());
- }
- /**
- * @brief Returns the associated allocator.
- * @return The associated allocator.
- */
- [[nodiscard]] constexpr allocator_type get_allocator() const ENTT_NOEXCEPT {
- return allocator_type{packed.second()};
- }
- /**
- * @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 ENTT_NOEXCEPT override {
- return packed.first().size() * comp_traits::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 ENTT_NOEXCEPT {
- return packed.first().data();
- }
- /*! @copydoc raw */
- [[nodiscard]] pointer raw() ENTT_NOEXCEPT {
- return packed.first().data();
- }
- /**
- * @brief Returns an iterator to the beginning.
- *
- * The returned iterator points to the first instance of the internal array.
- * 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 ENTT_NOEXCEPT {
- const auto pos = static_cast<typename iterator::difference_type>(base_type::size());
- return const_iterator{&packed.first(), pos};
- }
- /*! @copydoc cbegin */
- [[nodiscard]] const_iterator begin() const ENTT_NOEXCEPT {
- return cbegin();
- }
- /*! @copydoc begin */
- [[nodiscard]] iterator begin() ENTT_NOEXCEPT {
- const auto pos = static_cast<typename iterator::difference_type>(base_type::size());
- return iterator{&packed.first(), pos};
- }
- /**
- * @brief Returns an iterator to the end.
- *
- * The returned iterator points to the element following the last instance
- * of the internal array. Attempting to dereference the returned iterator
- * results in undefined behavior.
- *
- * @return An iterator to the element following the last instance of the
- * internal array.
- */
- [[nodiscard]] const_iterator cend() const ENTT_NOEXCEPT {
- return const_iterator{&packed.first(), {}};
- }
- /*! @copydoc cend */
- [[nodiscard]] const_iterator end() const ENTT_NOEXCEPT {
- return cend();
- }
- /*! @copydoc end */
- [[nodiscard]] iterator end() ENTT_NOEXCEPT {
- return iterator{&packed.first(), {}};
- }
- /**
- * @brief Returns a reverse iterator to the beginning.
- *
- * The returned iterator points to the first instance of the reversed
- * internal array. 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 ENTT_NOEXCEPT {
- return std::make_reverse_iterator(cend());
- }
- /*! @copydoc crbegin */
- [[nodiscard]] const_reverse_iterator rbegin() const ENTT_NOEXCEPT {
- return crbegin();
- }
- /*! @copydoc rbegin */
- [[nodiscard]] reverse_iterator rbegin() ENTT_NOEXCEPT {
- return std::make_reverse_iterator(end());
- }
- /**
- * @brief Returns a reverse iterator to the end.
- *
- * The returned iterator points to the element following the last instance
- * of the reversed internal array. Attempting to dereference the returned
- * iterator results in undefined behavior.
- *
- * @return An iterator to the element following the last instance of the
- * reversed internal array.
- */
- [[nodiscard]] const_reverse_iterator crend() const ENTT_NOEXCEPT {
- return std::make_reverse_iterator(cbegin());
- }
- /*! @copydoc crend */
- [[nodiscard]] const_reverse_iterator rend() const ENTT_NOEXCEPT {
- return crend();
- }
- /*! @copydoc rend */
- [[nodiscard]] reverse_iterator rend() ENTT_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 ENTT_NOEXCEPT {
- return element_at(base_type::index(entt));
- }
- /*! @copydoc get */
- [[nodiscard]] value_type &get(const entity_type entt) 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 ENTT_NOEXCEPT {
- return std::forward_as_tuple(get(entt));
- }
- /*! @copydoc get_as_tuple */
- [[nodiscard]] std::tuple<value_type &> get_as_tuple(const entity_type entt) 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>) {
- 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.
- */
- template<typename It>
- void insert(It first, It last, const value_type &value = {}) {
- for(; first != last; ++first) {
- emplace_element(*first, true, value);
- }
- }
- /**
- * @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.
- */
- template<typename EIt, typename CIt, typename = std::enable_if_t<std::is_same_v<typename std::iterator_traits<CIt>::value_type, value_type>>>
- void insert(EIt first, EIt last, CIt from) {
- for(; first != last; ++first, ++from) {
- emplace_element(*first, true, *from);
- }
- }
- /**
- * @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 component.
- *
- * @return An iterable object to use to _visit_ the storage.
- */
- [[nodiscard]] iterable each() ENTT_NOEXCEPT {
- return {internal::extended_storage_iterator{base_type::begin(), begin()}, internal::extended_storage_iterator{base_type::end(), end()}};
- }
- /*! @copydoc each */
- [[nodiscard]] const_iterable each() const ENTT_NOEXCEPT {
- return {internal::extended_storage_iterator{base_type::cbegin(), cbegin()}, internal::extended_storage_iterator{base_type::cend(), cend()}};
- }
- private:
- compressed_pair<container_type, allocator_type> packed;
- };
- /*! @copydoc basic_storage */
- template<typename Entity, typename Type, typename Allocator>
- class basic_storage<Entity, Type, Allocator, std::enable_if_t<ignore_as_empty_v<Type>>>
- : 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 underlying_type = basic_sparse_set<Entity, typename alloc_traits::template rebind_alloc<Entity>>;
- using comp_traits = component_traits<Type>;
- public:
- /*! @brief Base type. */
- using base_type = underlying_type;
- /*! @brief Allocator type. */
- using allocator_type = Allocator;
- /*! @brief Type of the objects assigned to entities. */
- using value_type = Type;
- /*! @brief Underlying entity identifier. */
- using entity_type = Entity;
- /*! @brief Unsigned integer type. */
- using size_type = std::size_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 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<value_type>(), deletion_policy{comp_traits::in_place_delete}, allocator} {}
- /**
- * @brief Move constructor.
- * @param other The instance to move from.
- */
- basic_storage(basic_storage &&other) ENTT_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) ENTT_NOEXCEPT
- : base_type{std::move(other), allocator} {}
- /**
- * @brief Move assignment operator.
- * @param other The instance to move from.
- * @return This storage.
- */
- basic_storage &operator=(basic_storage &&other) ENTT_NOEXCEPT = default;
- /**
- * @brief Returns the associated allocator.
- * @return The associated allocator.
- */
- [[nodiscard]] constexpr allocator_type get_allocator() const ENTT_NOEXCEPT {
- 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 ENTT_NOEXCEPT {
- ENTT_ASSERT(base_type::contains(entt), "Storage does not contain entity");
- }
- /**
- * @brief Returns an empty tuple.
- *
- * @warning
- * Attempting to use an entity that doesn't belong to the storage results in
- * undefined behavior.
- *
- * @param entt A valid identifier.
- * @return Returns an empty tuple.
- */
- [[nodiscard]] std::tuple<> get_as_tuple([[maybe_unused]] const entity_type entt) const ENTT_NOEXCEPT {
- ENTT_ASSERT(base_type::contains(entt), "Storage does not contain 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.
- *
- * @tparam Args Types of arguments to use to construct the object.
- * @param entt A valid identifier.
- */
- template<typename... Args>
- void emplace(const entity_type entt, Args &&...) {
- 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), "Storage does not contain entity");
- (std::forward<Func>(func)(), ...);
- }
- /**
- * @brief Assigns entities to a storage.
- * @tparam It Type of input iterator.
- * @tparam Args Types of optional arguments.
- * @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, typename... Args>
- void insert(It first, It last, Args &&...) {
- 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() ENTT_NOEXCEPT {
- return {internal::extended_storage_iterator{base_type::begin()}, internal::extended_storage_iterator{base_type::end()}};
- }
- /*! @copydoc each */
- [[nodiscard]] const_iterable each() const ENTT_NOEXCEPT {
- return {internal::extended_storage_iterator{base_type::cbegin()}, internal::extended_storage_iterator{base_type::cend()}};
- }
- };
- /**
- * @brief Provides a common way to access certain properties of storage types.
- * @tparam Entity A valid entity type (see entt_traits for more details).
- * @tparam Type Type of objects managed by the storage class.
- */
- template<typename Entity, typename Type, typename = void>
- struct storage_traits {
- /*! @brief Resulting type after component-to-storage conversion. */
- using storage_type = sigh_storage_mixin<basic_storage<Entity, Type>>;
- };
- } // namespace entt
- #endif
- // #include "entity/utility.hpp"
- #ifndef ENTT_ENTITY_UTILITY_HPP
- #define ENTT_ENTITY_UTILITY_HPP
- // #include "../core/type_traits.hpp"
- namespace entt {
- /**
- * @brief Alias for exclusion lists.
- * @tparam Type List of types.
- */
- template<typename... Type>
- struct exclude_t: type_list<Type...> {};
- /**
- * @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 components.
- * @tparam Type List of types.
- */
- template<typename... Type>
- struct get_t: type_list<Type...> {};
- /**
- * @brief Variable template for lists of observed components.
- * @tparam Type List of types.
- */
- template<typename... Type>
- inline constexpr get_t<Type...> get{};
- /**
- * @brief Alias for lists of owned components.
- * @tparam Type List of types.
- */
- template<typename... Type>
- struct owned_t: type_list<Type...> {};
- /**
- * @brief Variable template for lists of owned components.
- * @tparam Type List of types.
- */
- template<typename... Type>
- inline constexpr owned_t<Type...> owned{};
- } // namespace entt
- #endif
- // #include "entity/view.hpp"
- #ifndef ENTT_ENTITY_VIEW_HPP
- #define ENTT_ENTITY_VIEW_HPP
- #include <algorithm>
- #include <array>
- #include <iterator>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- // #include "../core/iterator.hpp"
- // #include "../core/type_traits.hpp"
- // #include "component.hpp"
- // #include "entity.hpp"
- // #include "fwd.hpp"
- // #include "sparse_set.hpp"
- // #include "storage.hpp"
- // #include "utility.hpp"
- namespace entt {
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- namespace internal {
- template<typename Type, std::size_t Component, std::size_t Exclude>
- class view_iterator final {
- using iterator_type = typename Type::const_iterator;
- [[nodiscard]] bool valid() const ENTT_NOEXCEPT {
- return ((Component != 0u) || (*it != tombstone))
- && std::apply([entt = *it](const auto *...curr) { return (curr->contains(entt) && ...); }, pools)
- && std::apply([entt = *it](const auto *...curr) { return (!curr->contains(entt) && ...); }, filter);
- }
- public:
- using value_type = typename iterator_type::value_type;
- using pointer = typename iterator_type::pointer;
- using reference = typename iterator_type::reference;
- using difference_type = typename iterator_type::difference_type;
- using iterator_category = std::forward_iterator_tag;
- view_iterator() ENTT_NOEXCEPT = default;
- view_iterator(iterator_type curr, iterator_type to, std::array<const Type *, Component> all_of, std::array<const Type *, Exclude> none_of) ENTT_NOEXCEPT
- : it{curr},
- last{to},
- pools{all_of},
- filter{none_of} {
- if(it != last && !valid()) {
- ++(*this);
- }
- }
- view_iterator &operator++() ENTT_NOEXCEPT {
- while(++it != last && !valid()) {}
- return *this;
- }
- view_iterator operator++(int) ENTT_NOEXCEPT {
- view_iterator orig = *this;
- return ++(*this), orig;
- }
- [[nodiscard]] pointer operator->() const ENTT_NOEXCEPT {
- return &*it;
- }
- [[nodiscard]] reference operator*() const ENTT_NOEXCEPT {
- return *operator->();
- }
- template<typename LhsType, auto... LhsArgs, typename RhsType, auto... RhsArgs>
- friend bool operator==(const view_iterator<LhsType, LhsArgs...> &, const view_iterator<RhsType, RhsArgs...> &) ENTT_NOEXCEPT;
- private:
- iterator_type it;
- iterator_type last;
- std::array<const Type *, Component> pools;
- std::array<const Type *, Exclude> filter;
- };
- template<typename LhsType, auto... LhsArgs, typename RhsType, auto... RhsArgs>
- [[nodiscard]] bool operator==(const view_iterator<LhsType, LhsArgs...> &lhs, const view_iterator<RhsType, RhsArgs...> &rhs) ENTT_NOEXCEPT {
- return lhs.it == rhs.it;
- }
- template<typename LhsType, auto... LhsArgs, typename RhsType, auto... RhsArgs>
- [[nodiscard]] bool operator!=(const view_iterator<LhsType, LhsArgs...> &lhs, const view_iterator<RhsType, RhsArgs...> &rhs) ENTT_NOEXCEPT {
- return !(lhs == rhs);
- }
- template<typename It, typename... Storage>
- struct extended_view_iterator final {
- using difference_type = std::ptrdiff_t;
- using value_type = decltype(std::tuple_cat(std::make_tuple(*std::declval<It>()), std::declval<Storage>().get_as_tuple({})...));
- using pointer = input_iterator_pointer<value_type>;
- using reference = value_type;
- using iterator_category = std::input_iterator_tag;
- extended_view_iterator() = default;
- extended_view_iterator(It from, std::tuple<Storage *...> storage)
- : it{from},
- pools{storage} {}
- extended_view_iterator &operator++() ENTT_NOEXCEPT {
- return ++it, *this;
- }
- extended_view_iterator operator++(int) ENTT_NOEXCEPT {
- extended_view_iterator orig = *this;
- return ++(*this), orig;
- }
- [[nodiscard]] reference operator*() const ENTT_NOEXCEPT {
- return std::apply([entt = *it](auto *...curr) { return std::tuple_cat(std::make_tuple(entt), curr->get_as_tuple(entt)...); }, pools);
- }
- [[nodiscard]] pointer operator->() const ENTT_NOEXCEPT {
- return operator*();
- }
- template<typename... Lhs, typename... Rhs>
- friend bool operator==(const extended_view_iterator<Lhs...> &, const extended_view_iterator<Rhs...> &) ENTT_NOEXCEPT;
- private:
- It it;
- std::tuple<Storage *...> pools;
- };
- template<typename... Lhs, typename... Rhs>
- [[nodiscard]] bool operator==(const extended_view_iterator<Lhs...> &lhs, const extended_view_iterator<Rhs...> &rhs) ENTT_NOEXCEPT {
- return lhs.it == rhs.it;
- }
- template<typename... Lhs, typename... Rhs>
- [[nodiscard]] bool operator!=(const extended_view_iterator<Lhs...> &lhs, const extended_view_iterator<Rhs...> &rhs) ENTT_NOEXCEPT {
- return !(lhs == rhs);
- }
- } // namespace internal
- /**
- * Internal details not to be documented.
- * @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.
- */
- template<typename, typename, typename, typename>
- class basic_view;
- /**
- * @brief Multi component view.
- *
- * Multi component views iterate over those entities that have at least all the
- * given components in their bags. During initialization, a multi component view
- * looks at the number of entities available for each component and uses the
- * smallest set in order to get a performance boost when iterate.
- *
- * @b Important
- *
- * Iterators aren't invalidated if:
- *
- * * New instances of the given components are created and assigned to entities.
- * * The entity currently pointed is modified (as an example, if one of the
- * given components is removed from the entity to which the iterator points).
- * * The entity currently pointed is destroyed.
- *
- * In all other cases, modifying the pools iterated by the view in any way
- * invalidates all the iterators and using them results in undefined behavior.
- *
- * @tparam Entity A valid entity type (see entt_traits for more details).
- * @tparam Component Types of components iterated by the view.
- * @tparam Exclude Types of components used to filter the view.
- */
- template<typename Entity, typename... Component, typename... Exclude>
- class basic_view<Entity, get_t<Component...>, exclude_t<Exclude...>> {
- template<typename, typename, typename, typename>
- friend class basic_view;
- template<typename Comp>
- using storage_type = constness_as_t<typename storage_traits<Entity, std::remove_const_t<Comp>>::storage_type, Comp>;
- template<std::size_t... Index>
- [[nodiscard]] auto pools_to_array(std::index_sequence<Index...>) const ENTT_NOEXCEPT {
- std::size_t pos{};
- std::array<const base_type *, sizeof...(Component) - 1u> other{};
- (static_cast<void>(std::get<Index>(pools) == view ? void() : void(other[pos++] = std::get<Index>(pools))), ...);
- return other;
- }
- template<std::size_t Comp, std::size_t Other, typename... Args>
- [[nodiscard]] auto dispatch_get(const std::tuple<Entity, Args...> &curr) const {
- if constexpr(Comp == Other) {
- return std::forward_as_tuple(std::get<Args>(curr)...);
- } else {
- return std::get<Other>(pools)->get_as_tuple(std::get<0>(curr));
- }
- }
- template<std::size_t Comp, typename Func, std::size_t... Index>
- void each(Func func, std::index_sequence<Index...>) const {
- for(const auto curr: std::get<Comp>(pools)->each()) {
- const auto entt = std::get<0>(curr);
- if(((sizeof...(Component) != 1u) || (entt != tombstone))
- && ((Comp == Index || std::get<Index>(pools)->contains(entt)) && ...)
- && std::apply([entt](const auto *...cpool) { return (!cpool->contains(entt) && ...); }, filter)) {
- 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<Comp, Index>(curr)...));
- } else {
- std::apply(func, std::tuple_cat(dispatch_get<Comp, Index>(curr)...));
- }
- }
- }
- }
- template<typename Func, std::size_t... Index>
- void pick_and_each(Func func, std::index_sequence<Index...> seq) const {
- ((std::get<Index>(pools) == view ? each<Index>(std::move(func), seq) : void()), ...);
- }
- public:
- /*! @brief Underlying entity identifier. */
- using entity_type = Entity;
- /*! @brief Unsigned integer type. */
- using size_type = std::size_t;
- /*! @brief Common type among all storage types. */
- using base_type = std::common_type_t<typename storage_type<Component>::base_type...>;
- /*! @brief Bidirectional iterator type. */
- using iterator = internal::view_iterator<base_type, sizeof...(Component) - 1u, sizeof...(Exclude)>;
- /*! @brief Iterable view type. */
- using iterable = iterable_adaptor<internal::extended_view_iterator<iterator, storage_type<Component>...>>;
- /*! @brief Default constructor to use to create empty, invalid views. */
- basic_view() ENTT_NOEXCEPT
- : pools{},
- filter{},
- view{} {}
- /**
- * @brief Constructs a multi-type view from a set of storage classes.
- * @param component The storage for the types to iterate.
- * @param epool The storage for the types used to filter the view.
- */
- basic_view(storage_type<Component> &...component, const storage_type<Exclude> &...epool) ENTT_NOEXCEPT
- : pools{&component...},
- filter{&epool...},
- view{(std::min)({&static_cast<const base_type &>(component)...}, [](auto *lhs, auto *rhs) { return lhs->size() < rhs->size(); })} {}
- /**
- * @brief Creates a new view driven by a given component in its iterations.
- * @tparam Comp Type of component used to drive the iteration.
- * @return A new view driven by the given component in its iterations.
- */
- template<typename Comp>
- [[nodiscard]] basic_view use() const ENTT_NOEXCEPT {
- basic_view other{*this};
- other.view = std::get<storage_type<Comp> *>(pools);
- return other;
- }
- /**
- * @brief Creates a new view driven by a given component in its iterations.
- * @tparam Comp Index of the component used to drive the iteration.
- * @return A new view driven by the given component in its iterations.
- */
- template<std::size_t Comp>
- [[nodiscard]] basic_view use() const ENTT_NOEXCEPT {
- basic_view other{*this};
- other.view = std::get<Comp>(pools);
- return other;
- }
- /**
- * @brief Returns the leading storage of a view.
- * @return The leading storage of the view.
- */
- const base_type &handle() const ENTT_NOEXCEPT {
- return *view;
- }
- /**
- * @brief Returns the storage for a given component type.
- * @tparam Comp Type of component of which to return the storage.
- * @return The storage for the given component type.
- */
- template<typename Comp>
- [[nodiscard]] decltype(auto) storage() const ENTT_NOEXCEPT {
- return *std::get<storage_type<Comp> *>(pools);
- }
- /**
- * @brief Returns the storage for a given component type.
- * @tparam Comp Index of component of which to return the storage.
- * @return The storage for the given component type.
- */
- template<std::size_t Comp>
- [[nodiscard]] decltype(auto) storage() const ENTT_NOEXCEPT {
- return *std::get<Comp>(pools);
- }
- /**
- * @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 ENTT_NOEXCEPT {
- return view->size();
- }
- /**
- * @brief Returns an iterator to the first entity of the view.
- *
- * The returned iterator points 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 ENTT_NOEXCEPT {
- return iterator{view->begin(), view->end(), pools_to_array(std::index_sequence_for<Component...>{}), filter};
- }
- /**
- * @brief Returns an iterator that is past the last entity of the view.
- *
- * The returned iterator points to the entity following the last entity of
- * the view. Attempting to dereference the returned iterator results in
- * undefined behavior.
- *
- * @return An iterator to the entity following the last entity of the view.
- */
- [[nodiscard]] iterator end() const ENTT_NOEXCEPT {
- return iterator{view->end(), view->end(), pools_to_array(std::index_sequence_for<Component...>{}), filter};
- }
- /**
- * @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 ENTT_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 ENTT_NOEXCEPT {
- auto it = view->rbegin();
- for(const auto last = view->rend(); it != last && !contains(*it); ++it) {}
- return it == view->rend() ? null : *it;
- }
- /**
- * @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 ENTT_NOEXCEPT {
- return contains(entt) ? iterator{view->find(entt), view->end(), pools_to_array(std::index_sequence_for<Component...>{}), filter} : end();
- }
- /**
- * @brief Returns the components assigned to the given entity.
- * @param entt A valid identifier.
- * @return The components assigned to the given entity.
- */
- [[nodiscard]] decltype(auto) operator[](const entity_type entt) const {
- return get<Component...>(entt);
- }
- /**
- * @brief Checks if a view is properly initialized.
- * @return True if the view is properly initialized, false otherwise.
- */
- [[nodiscard]] explicit operator bool() const ENTT_NOEXCEPT {
- return view != 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 ENTT_NOEXCEPT {
- return std::apply([entt](const auto *...curr) { return (curr->contains(entt) && ...); }, pools)
- && std::apply([entt](const auto *...curr) { return (!curr->contains(entt) && ...); }, filter);
- }
- /**
- * @brief Returns the components assigned to the given entity.
- *
- * @warning
- * Attempting to use an entity that doesn't belong to the view results in
- * undefined behavior.
- *
- * @tparam Comp Types of components to get.
- * @param entt A valid identifier.
- * @return The components assigned to the entity.
- */
- template<typename... Comp>
- [[nodiscard]] decltype(auto) get(const entity_type entt) const {
- ENTT_ASSERT(contains(entt), "View does not contain entity");
- if constexpr(sizeof...(Comp) == 0) {
- return std::apply([entt](auto *...curr) { return std::tuple_cat(curr->get_as_tuple(entt)...); }, pools);
- } else if constexpr(sizeof...(Comp) == 1) {
- return (std::get<storage_type<Comp> *>(pools)->get(entt), ...);
- } else {
- return std::tuple_cat(std::get<storage_type<Comp> *>(pools)->get_as_tuple(entt)...);
- }
- }
- /**
- * @brief Returns the components assigned to the given entity.
- *
- * @warning
- * Attempting to use an entity that doesn't belong to the view results in
- * undefined behavior.
- *
- * @tparam First Index of a component to get.
- * @tparam Other Indexes of other components to get.
- * @param entt A valid identifier.
- * @return The components assigned to the entity.
- */
- template<std::size_t First, std::size_t... Other>
- [[nodiscard]] decltype(auto) get(const entity_type entt) const {
- ENTT_ASSERT(contains(entt), "View does not contain entity");
- if constexpr(sizeof...(Other) == 0) {
- return std::get<First>(pools)->get(entt);
- } else {
- return std::tuple_cat(std::get<First>(pools)->get_as_tuple(entt), std::get<Other>(pools)->get_as_tuple(entt)...);
- }
- }
- /**
- * @brief Iterates entities and components 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 components. The
- * _constness_ of the components 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
- *
- * @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(std::move(func), std::index_sequence_for<Component...>{});
- }
- /**
- * @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 components. The _constness_ of the
- * components is as requested.
- *
- * @return An iterable object to use to _visit_ the view.
- */
- [[nodiscard]] iterable each() const ENTT_NOEXCEPT {
- return {internal::extended_view_iterator{begin(), pools}, internal::extended_view_iterator{end(), pools}};
- }
- /**
- * @brief Combines two views in a _more specific_ one (friend function).
- * @tparam Get Component list of the view to combine with.
- * @tparam Excl Filter list of the view to combine with.
- * @param other The view to combine with.
- * @return A more specific view.
- */
- template<typename... Get, typename... Excl>
- [[nodiscard]] auto operator|(const basic_view<Entity, get_t<Get...>, exclude_t<Excl...>> &other) const ENTT_NOEXCEPT {
- using view_type = basic_view<Entity, get_t<Component..., Get...>, exclude_t<Exclude..., Excl...>>;
- return std::make_from_tuple<view_type>(std::tuple_cat(
- std::apply([](auto *...curr) { return std::forward_as_tuple(*curr...); }, pools),
- std::apply([](auto *...curr) { return std::forward_as_tuple(*curr...); }, other.pools),
- std::apply([](const auto *...curr) { return std::forward_as_tuple(static_cast<const storage_type<Exclude> &>(*curr)...); }, filter),
- std::apply([](const auto *...curr) { return std::forward_as_tuple(static_cast<const storage_type<Excl> &>(*curr)...); }, other.filter)));
- }
- private:
- std::tuple<storage_type<Component> *...> pools;
- std::array<const base_type *, sizeof...(Exclude)> filter;
- const base_type *view;
- };
- /**
- * @brief Single component view specialization.
- *
- * Single component views are specialized in order to get a boost in terms of
- * performance. This kind of views can access the underlying data structure
- * directly and avoid superfluous checks.
- *
- * @b Important
- *
- * Iterators aren't invalidated if:
- *
- * * New instances of the given component are created and assigned to entities.
- * * The entity currently pointed is modified (as an example, the given
- * component is removed from the entity to which the iterator points).
- * * The entity currently pointed is destroyed.
- *
- * In all other cases, modifying the pool iterated by the view in any way
- * invalidates all the iterators and using them results in undefined behavior.
- *
- * @tparam Entity A valid entity type (see entt_traits for more details).
- * @tparam Component Type of component iterated by the view.
- */
- template<typename Entity, typename Component>
- class basic_view<Entity, get_t<Component>, exclude_t<>, std::void_t<std::enable_if_t<!component_traits<std::remove_const_t<Component>>::in_place_delete>>> {
- template<typename, typename, typename, typename>
- friend class basic_view;
- using storage_type = constness_as_t<typename storage_traits<Entity, std::remove_const_t<Component>>::storage_type, Component>;
- public:
- /*! @brief Underlying entity identifier. */
- using entity_type = Entity;
- /*! @brief Unsigned integer type. */
- using size_type = std::size_t;
- /*! @brief Common type among all storage types. */
- using base_type = typename storage_type::base_type;
- /*! @brief Random access iterator type. */
- using iterator = typename base_type::iterator;
- /*! @brief Reversed iterator type. */
- using reverse_iterator = typename base_type::reverse_iterator;
- /*! @brief Iterable view type. */
- using iterable = decltype(std::declval<storage_type>().each());
- /*! @brief Default constructor to use to create empty, invalid views. */
- basic_view() ENTT_NOEXCEPT
- : pools{},
- filter{},
- view{} {}
- /**
- * @brief Constructs a single-type view from a storage class.
- * @param ref The storage for the type to iterate.
- */
- basic_view(storage_type &ref) ENTT_NOEXCEPT
- : pools{&ref},
- filter{},
- view{&ref} {}
- /**
- * @brief Returns the leading storage of a view.
- * @return The leading storage of the view.
- */
- const base_type &handle() const ENTT_NOEXCEPT {
- return *view;
- }
- /**
- * @brief Returns the storage for a given component type.
- * @tparam Comp Type of component of which to return the storage.
- * @return The storage for the given component type.
- */
- template<typename Comp = Component>
- [[nodiscard]] decltype(auto) storage() const ENTT_NOEXCEPT {
- static_assert(std::is_same_v<Comp, Component>, "Invalid component type");
- return *std::get<0>(pools);
- }
- /**
- * @brief Returns the storage for a given component type.
- * @tparam Comp Index of component of which to return the storage.
- * @return The storage for the given component type.
- */
- template<std::size_t Comp>
- [[nodiscard]] decltype(auto) storage() const ENTT_NOEXCEPT {
- return *std::get<Comp>(pools);
- }
- /**
- * @brief Returns the number of entities that have the given component.
- * @return Number of entities that have the given component.
- */
- [[nodiscard]] size_type size() const ENTT_NOEXCEPT {
- return view->size();
- }
- /**
- * @brief Checks whether a view is empty.
- * @return True if the view is empty, false otherwise.
- */
- [[nodiscard]] bool empty() const ENTT_NOEXCEPT {
- return view->empty();
- }
- /**
- * @brief Returns an iterator to the first entity of the view.
- *
- * The returned iterator points 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 ENTT_NOEXCEPT {
- return view->begin();
- }
- /**
- * @brief Returns an iterator that is past the last entity of the view.
- *
- * The returned iterator points to the entity following the last entity of
- * the view. Attempting to dereference the returned iterator results in
- * undefined behavior.
- *
- * @return An iterator to the entity following the last entity of the view.
- */
- [[nodiscard]] iterator end() const ENTT_NOEXCEPT {
- return view->end();
- }
- /**
- * @brief Returns an iterator to the first entity of the reversed view.
- *
- * The returned iterator points to the first entity of the reversed view. If
- * the view is empty, the returned iterator will be equal to `rend()`.
- *
- * @return An iterator to the first entity of the reversed view.
- */
- [[nodiscard]] reverse_iterator rbegin() const ENTT_NOEXCEPT {
- return view->rbegin();
- }
- /**
- * @brief Returns an iterator that is past the last entity of the reversed
- * view.
- *
- * The returned iterator points to the entity following the last entity of
- * the reversed view. Attempting to dereference the returned iterator
- * results in undefined behavior.
- *
- * @return An iterator to the entity following the last entity of the
- * reversed view.
- */
- [[nodiscard]] reverse_iterator rend() const ENTT_NOEXCEPT {
- return view->rend();
- }
- /**
- * @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 ENTT_NOEXCEPT {
- return empty() ? null : *begin();
- }
- /**
- * @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 ENTT_NOEXCEPT {
- return empty() ? null : *rbegin();
- }
- /**
- * @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 ENTT_NOEXCEPT {
- return contains(entt) ? view->find(entt) : end();
- }
- /**
- * @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()[pos];
- }
- /**
- * @brief Returns the component assigned to the given entity.
- * @param entt A valid identifier.
- * @return The component assigned to the given entity.
- */
- [[nodiscard]] decltype(auto) operator[](const entity_type entt) const {
- return get<Component>(entt);
- }
- /**
- * @brief Checks if a view is properly initialized.
- * @return True if the view is properly initialized, false otherwise.
- */
- [[nodiscard]] explicit operator bool() const ENTT_NOEXCEPT {
- return view != 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 ENTT_NOEXCEPT {
- return view->contains(entt);
- }
- /**
- * @brief Returns the component assigned to the given entity.
- *
- * @warning
- * Attempting to use an entity that doesn't belong to the view results in
- * undefined behavior.
- *
- * @tparam Comp Type or index of the component to get.
- * @param entt A valid identifier.
- * @return The component assigned to the entity.
- */
- template<typename... Comp>
- [[nodiscard]] decltype(auto) get(const entity_type entt) const {
- ENTT_ASSERT(contains(entt), "View does not contain entity");
- if constexpr(sizeof...(Comp) == 0) {
- return std::get<0>(pools)->get_as_tuple(entt);
- } else {
- static_assert(std::is_same_v<Comp..., Component>, "Invalid component type");
- return std::get<0>(pools)->get(entt);
- }
- }
- /*! @copydoc get */
- template<std::size_t Comp>
- [[nodiscard]] decltype(auto) get(const entity_type entt) const {
- ENTT_ASSERT(contains(entt), "View does not contain entity");
- return std::get<0>(pools)->get(entt);
- }
- /**
- * @brief Iterates entities and components 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 reference to the component if it's a non-empty one.
- * The _constness_ of the component is as requested.<br/>
- * The signature of the function must be equivalent to one of the following
- * forms:
- *
- * @code{.cpp}
- * void(const entity_type, Component &);
- * void(Component &);
- * @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(*each().begin())>) {
- for(const auto pack: each()) {
- std::apply(func, pack);
- }
- } else if constexpr(std::is_invocable_v<Func, Component &>) {
- for(auto &&component: *std::get<0>(pools)) {
- func(component);
- }
- } else if constexpr(std::is_invocable_v<Func, Entity>) {
- for(auto entity: *view) {
- func(entity);
- }
- } else {
- for(size_type pos{}, last = size(); pos < last; ++pos) {
- func();
- }
- }
- }
- /**
- * @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 component if it's a non-empty one. The _constness_ of
- * the component is as requested.
- *
- * @return An iterable object to use to _visit_ the view.
- */
- [[nodiscard]] iterable each() const ENTT_NOEXCEPT {
- return std::get<0>(pools)->each();
- }
- /**
- * @brief Combines two views in a _more specific_ one (friend function).
- * @tparam Get Component list of the view to combine with.
- * @tparam Excl Filter list of the view to combine with.
- * @param other The view to combine with.
- * @return A more specific view.
- */
- template<typename... Get, typename... Excl>
- [[nodiscard]] auto operator|(const basic_view<Entity, get_t<Get...>, exclude_t<Excl...>> &other) const ENTT_NOEXCEPT {
- using view_type = basic_view<Entity, get_t<Component, Get...>, exclude_t<Excl...>>;
- return std::make_from_tuple<view_type>(std::tuple_cat(
- std::forward_as_tuple(*std::get<0>(pools)),
- std::apply([](auto *...curr) { return std::forward_as_tuple(*curr...); }, other.pools),
- std::apply([](const auto *...curr) { return std::forward_as_tuple(static_cast<const typename view_type::template storage_type<Excl> &>(*curr)...); }, other.filter)));
- }
- private:
- std::tuple<storage_type *> pools;
- std::array<const base_type *, 0u> filter;
- const base_type *view;
- };
- /**
- * @brief Deduction guide.
- * @tparam Storage Type of storage classes used to create the view.
- * @param storage The storage for the types to iterate.
- */
- template<typename... Storage>
- basic_view(Storage &...storage) -> basic_view<std::common_type_t<typename Storage::entity_type...>, get_t<constness_as_t<typename Storage::value_type, Storage>...>, exclude_t<>>;
- } // 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
- #define ENTT_STR(arg) #arg
- #define ENTT_XSTR(arg) ENTT_STR(arg)
- #endif
- #define ENTT_VERSION_MAJOR 3
- #define ENTT_VERSION_MINOR 10
- #define ENTT_VERSION_PATCH 3
- #define ENTT_VERSION \
- ENTT_XSTR(ENTT_VERSION_MAJOR) \
- "." ENTT_XSTR(ENTT_VERSION_MINOR) "." ENTT_XSTR(ENTT_VERSION_PATCH)
- #endif
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #ifndef ENTT_NOEXCEPT
- # define ENTT_NOEXCEPT noexcept
- # define ENTT_NOEXCEPT_IF(expr) noexcept(expr)
- # else
- # define ENTT_NOEXCEPT_IF(...)
- #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
- #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(...) (void(0))
- #elif !defined ENTT_ASSERT
- # include <cassert>
- # define ENTT_ASSERT(condition, ...) assert(condition)
- #endif
- #ifdef ENTT_NO_ETO
- # define ENTT_IGNORE_IF_EMPTY false
- #else
- # define ENTT_IGNORE_IF_EMPTY true
- #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
- #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
- #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>
- struct locator final {
- /*! @brief Service type. */
- using type = Service;
- /*! @brief Default constructor, deleted on purpose. */
- locator() = delete;
- /*! @brief Default destructor, deleted on purpose. */
- ~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() ENTT_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() ENTT_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 Impl Fallback service type.
- * @param args Parameters to use to construct the fallback service.
- * @return A reference to a valid service.
- */
- template<typename Impl = Service, typename... Args>
- [[nodiscard]] static Service &value_or(Args &&...args) {
- return service ? *service : emplace<Impl>(std::forward<Args>(args)...);
- }
- /**
- * @brief Sets or replaces a service.
- * @tparam Impl 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 Impl = Service, typename... Args>
- static Service &emplace(Args &&...args) {
- service = std::make_shared<Impl>(std::forward<Args>(args)...);
- return *service;
- }
- /**
- * @brief Sets or replaces a service using a given allocator.
- * @tparam Impl 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 Impl = Service, typename Allocator, typename... Args>
- static Service &allocate_emplace(Allocator alloc, Args &&...args) {
- service = std::allocate_shared<Impl>(alloc, std::forward<Args>(args)...);
- return *service;
- }
- /*! @brief Resets a service. */
- static void reset() ENTT_NOEXCEPT {
- service.reset();
- }
- private:
- // std::shared_ptr because of its type erased allocator which is pretty useful here
- inline static std::shared_ptr<Service> service = nullptr;
- };
- } // 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"
- #ifndef ENTT_META_CONTAINER_HPP
- #define ENTT_META_CONTAINER_HPP
- #include <array>
- #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 <algorithm>
- #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
- #define ENTT_STR(arg) #arg
- #define ENTT_XSTR(arg) ENTT_STR(arg)
- #endif
- #define ENTT_VERSION_MAJOR 3
- #define ENTT_VERSION_MINOR 10
- #define ENTT_VERSION_PATCH 3
- #define ENTT_VERSION \
- ENTT_XSTR(ENTT_VERSION_MAJOR) \
- "." ENTT_XSTR(ENTT_VERSION_MINOR) "." ENTT_XSTR(ENTT_VERSION_PATCH)
- #endif
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #ifndef ENTT_NOEXCEPT
- # define ENTT_NOEXCEPT noexcept
- # define ENTT_NOEXCEPT_IF(expr) noexcept(expr)
- # else
- # define ENTT_NOEXCEPT_IF(...)
- #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
- #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(...) (void(0))
- #elif !defined ENTT_ASSERT
- # include <cassert>
- # define ENTT_ASSERT(condition, ...) assert(condition)
- #endif
- #ifdef ENTT_NO_ETO
- # define ENTT_IGNORE_IF_EMPTY false
- #else
- # define ENTT_IGNORE_IF_EMPTY true
- #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
- #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
- #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 "../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
- #define ENTT_STR(arg) #arg
- #define ENTT_XSTR(arg) ENTT_STR(arg)
- #endif
- #define ENTT_VERSION_MAJOR 3
- #define ENTT_VERSION_MINOR 10
- #define ENTT_VERSION_PATCH 3
- #define ENTT_VERSION \
- ENTT_XSTR(ENTT_VERSION_MAJOR) \
- "." ENTT_XSTR(ENTT_VERSION_MINOR) "." ENTT_XSTR(ENTT_VERSION_PATCH)
- #endif
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #ifndef ENTT_NOEXCEPT
- # define ENTT_NOEXCEPT noexcept
- # define ENTT_NOEXCEPT_IF(expr) noexcept(expr)
- # else
- # define ENTT_NOEXCEPT_IF(...)
- #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
- #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(...) (void(0))
- #elif !defined ENTT_ASSERT
- # include <cassert>
- # define ENTT_ASSERT(condition, ...) assert(condition)
- #endif
- #ifdef ENTT_NO_ETO
- # define ENTT_IGNORE_IF_EMPTY false
- #else
- # define ENTT_IGNORE_IF_EMPTY true
- #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
- #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
- #endif
- // #include "type_traits.hpp"
- #ifndef ENTT_CORE_TYPE_TRAITS_HPP
- #define ENTT_CORE_TYPE_TRAITS_HPP
- #include <cstddef>
- #include <iterator>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- // #include "fwd.hpp"
- #ifndef ENTT_CORE_FWD_HPP
- #define ENTT_CORE_FWD_HPP
- #include <cstdint>
- #include <type_traits>
- // #include "../config/config.h"
- namespace entt {
- template<std::size_t Len = sizeof(double[2]), std::size_t = alignof(typename std::aligned_storage_t<Len + !Len>)>
- 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<>;
- } // 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.
- * @tparam The size of the type if `sizeof` accepts it, 0 otherwise.
- */
- 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))>>
- : 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 Type First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<std::size_t Index, typename Type, typename... Other>
- struct type_list_element<Index, type_list<Type, Other...>>
- : type_list_element<Index - 1u, type_list<Other...>> {};
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam Type First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<typename Type, typename... Other>
- struct type_list_element<0u, type_list<Type, Other...>> {
- /*! @brief Searched type. */
- using type = Type;
- };
- /**
- * @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 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;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename>
- struct type_list_unique;
- /**
- * @brief Removes duplicates types from a type list.
- * @tparam Type One of the types provided by the given type list.
- * @tparam Other The other types provided by the given type list.
- */
- template<typename Type, typename... Other>
- struct type_list_unique<type_list<Type, Other...>> {
- /*! @brief A type list without duplicate types. */
- using type = std::conditional_t<
- (std::is_same_v<Type, Other> || ...),
- typename type_list_unique<type_list<Other...>>::type,
- type_list_cat_t<type_list<Type>, typename type_list_unique<type_list<Other...>>::type>>;
- };
- /*! @brief Removes duplicates types from a type list. */
- template<>
- struct type_list_unique<type_list<>> {
- /*! @brief A type list without duplicate types. */
- using type = type_list<>;
- };
- /**
- * @brief Helper type.
- * @tparam Type A type list.
- */
- template<typename Type>
- using type_list_unique_t = typename type_list_unique<Type>::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::disjunction<std::is_same<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 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 value. */
- static constexpr auto value = Value;
- };
- /**
- * @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 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 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
- * Internal details not to be documented.
- */
- 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
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /*! @copydoc is_iterator */
- template<typename Type>
- struct is_iterator<Type, std::enable_if_t<!std::is_same_v<std::remove_const_t<std::remove_pointer_t<Type>>, void>>>
- : 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::conjunction<std::is_empty<Type>, std::negation<std::is_final<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;
- /**
- * @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, typename = void>
- struct is_equality_comparable: std::false_type {};
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- 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 Type, std::size_t... Index>
- [[nodiscard]] constexpr bool unpack_maybe_equality_comparable(std::index_sequence<Index...>) {
- return (is_equality_comparable<std::tuple_element_t<Index, Type>>::value && ...);
- }
- template<typename>
- [[nodiscard]] constexpr bool maybe_equality_comparable(choice_t<0>) {
- return true;
- }
- template<typename Type>
- [[nodiscard]] constexpr auto maybe_equality_comparable(choice_t<1>) -> decltype(std::declval<typename Type::value_type>(), bool{}) {
- if constexpr(is_iterator_v<Type>) {
- return true;
- } else if constexpr(std::is_same_v<typename Type::value_type, Type>) {
- return maybe_equality_comparable<Type>(choice<0>);
- } else {
- return is_equality_comparable<typename Type::value_type>::value;
- }
- }
- template<typename Type>
- [[nodiscard]] constexpr std::enable_if_t<is_complete_v<std::tuple_size<std::remove_const_t<Type>>>, bool> maybe_equality_comparable(choice_t<2>) {
- if constexpr(has_tuple_size_value<Type>::value) {
- return unpack_maybe_equality_comparable<Type>(std::make_index_sequence<std::tuple_size<Type>::value>{});
- } else {
- return maybe_equality_comparable<Type>(choice<1>);
- }
- }
- } // namespace internal
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /*! @copydoc is_equality_comparable */
- template<typename Type>
- struct is_equality_comparable<Type, std::void_t<decltype(std::declval<Type>() == std::declval<Type>())>>
- : std::bool_constant<internal::maybe_equality_comparable<Type>(choice<2>)> {};
- /**
- * @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 = std::add_const_t<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;
- } // namespace entt
- #endif
- namespace entt {
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- namespace internal {
- template<typename Type, std::size_t, typename = void>
- struct compressed_pair_element {
- using reference = Type &;
- using const_reference = const Type &;
- template<bool Dummy = true, typename = std::enable_if_t<Dummy && std::is_default_constructible_v<Type>>>
- compressed_pair_element()
- : value{} {}
- template<typename Args, typename = std::enable_if_t<!std::is_same_v<std::remove_cv_t<std::remove_reference_t<Args>>, compressed_pair_element>>>
- compressed_pair_element(Args &&args)
- : value{std::forward<Args>(args)} {}
- template<typename... Args, std::size_t... Index>
- compressed_pair_element(std::tuple<Args...> args, std::index_sequence<Index...>)
- : value{std::forward<Args>(std::get<Index>(args))...} {}
- [[nodiscard]] reference get() ENTT_NOEXCEPT {
- return value;
- }
- [[nodiscard]] const_reference get() const ENTT_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<bool Dummy = true, typename = std::enable_if_t<Dummy && std::is_default_constructible_v<base_type>>>
- compressed_pair_element()
- : base_type{} {}
- template<typename Args, typename = std::enable_if_t<!std::is_same_v<std::remove_cv_t<std::remove_reference_t<Args>>, compressed_pair_element>>>
- compressed_pair_element(Args &&args)
- : base_type{std::forward<Args>(args)} {}
- template<typename... Args, std::size_t... Index>
- compressed_pair_element(std::tuple<Args...> args, std::index_sequence<Index...>)
- : base_type{std::forward<Args>(std::get<Index>(args))...} {}
- [[nodiscard]] reference get() ENTT_NOEXCEPT {
- return *this;
- }
- [[nodiscard]] const_reference get() const ENTT_NOEXCEPT {
- return *this;
- }
- };
- } // namespace internal
- /**
- * Internal details not to be documented.
- * @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()
- : 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) = 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)
- : 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)
- : first_base{std::move(args), std::index_sequence_for<Args...>{}},
- second_base{std::move(other), std::index_sequence_for<Other...>{}} {}
- /**
- * @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) = default;
- /**
- * @brief Returns the first element that a pair stores.
- * @return The first element that a pair stores.
- */
- [[nodiscard]] first_type &first() ENTT_NOEXCEPT {
- return static_cast<first_base &>(*this).get();
- }
- /*! @copydoc first */
- [[nodiscard]] const first_type &first() const ENTT_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]] second_type &second() ENTT_NOEXCEPT {
- return static_cast<second_base &>(*this).get();
- }
- /*! @copydoc second */
- [[nodiscard]] const second_type &second() const ENTT_NOEXCEPT {
- return static_cast<const second_base &>(*this).get();
- }
- /**
- * @brief Swaps two compressed pair objects.
- * @param other The compressed pair to swap with.
- */
- void swap(compressed_pair &other) {
- 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>
- decltype(auto) get() ENTT_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>
- decltype(auto) get() const ENTT_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>
- inline void swap(compressed_pair<First, Second> &lhs, compressed_pair<First, Second> &rhs) {
- lhs.swap(rhs);
- }
- } // namespace entt
- // disable structured binding support for clang 6, it messes when specializing tuple_size
- #if !defined __clang_major__ || __clang_major__ > 6
- 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
- #endif
- // #include "../core/iterator.hpp"
- #ifndef ENTT_CORE_ITERATOR_HPP
- #define ENTT_CORE_ITERATOR_HPP
- #include <iterator>
- #include <memory>
- #include <utility>
- // #include "../config/config.h"
- 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 Pointer type. */
- using pointer = Type *;
- /*! @brief Default copy constructor, deleted on purpose. */
- input_iterator_pointer(const input_iterator_pointer &) = delete;
- /*! @brief Default move constructor. */
- input_iterator_pointer(input_iterator_pointer &&) = default;
- /**
- * @brief Constructs a proxy object by move.
- * @param val Value to use to initialize the proxy object.
- */
- input_iterator_pointer(Type &&val)
- : value{std::move(val)} {}
- /**
- * @brief Default copy assignment operator, deleted on purpose.
- * @return This proxy object.
- */
- input_iterator_pointer &operator=(const input_iterator_pointer &) = delete;
- /**
- * @brief Default move assignment operator.
- * @return This proxy object.
- */
- input_iterator_pointer &operator=(input_iterator_pointer &&) = default;
- /**
- * @brief Access operator for accessing wrapped values.
- * @return A pointer to the wrapped value.
- */
- [[nodiscard]] pointer operator->() ENTT_NOEXCEPT {
- return std::addressof(value);
- }
- private:
- Type value;
- };
- /**
- * @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. */
- iterable_adaptor() = default;
- /**
- * @brief Creates an iterable object from a pair of iterators.
- * @param from Begin iterator.
- * @param to End iterator.
- */
- iterable_adaptor(iterator from, sentinel to)
- : first{from},
- last{to} {}
- /**
- * @brief Returns an iterator to the beginning.
- * @return An iterator to the first element of the range.
- */
- [[nodiscard]] iterator begin() const ENTT_NOEXCEPT {
- return first;
- }
- /**
- * @brief Returns an iterator to the end.
- * @return An iterator to the element following the last element of the
- * range.
- */
- [[nodiscard]] sentinel end() const ENTT_NOEXCEPT {
- return last;
- }
- /*! @copydoc begin */
- [[nodiscard]] iterator cbegin() const ENTT_NOEXCEPT {
- return begin();
- }
- /*! @copydoc end */
- [[nodiscard]] sentinel cend() const ENTT_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 <limits>
- #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) ENTT_NOEXCEPT {
- if constexpr(std::is_pointer_v<std::remove_cv_t<std::remove_reference_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) ENTT_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) ENTT_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) ENTT_NOEXCEPT {
- ENTT_ASSERT(std::allocator_traits<Allocator>::propagate_on_container_swap::value || lhs == rhs, "Cannot swap the containers");
- if constexpr(std::allocator_traits<Allocator>::propagate_on_container_swap::value) {
- using std::swap;
- swap(lhs, rhs);
- }
- }
- /**
- * @brief Checks whether a value is a power of two or not.
- * @param value A value that may or may not be a power of two.
- * @return True if the value is a power of two, false otherwise.
- */
- [[nodiscard]] inline constexpr bool is_power_of_two(const std::size_t value) ENTT_NOEXCEPT {
- return value && ((value & (value - 1)) == 0);
- }
- /**
- * @brief Computes the smallest power of two greater than or equal to a value.
- * @param value The value to use.
- * @return The smallest power of two greater than or equal to the given value.
- */
- [[nodiscard]] inline constexpr std::size_t next_power_of_two(const std::size_t value) ENTT_NOEXCEPT {
- ENTT_ASSERT(value < (std::size_t{1u} << (std::numeric_limits<std::size_t>::digits - 1)), "Numeric limits exceeded");
- std::size_t curr = value - (value != 0u);
- for(int next = 1; next < std::numeric_limits<std::size_t>::digits; next = next * 2) {
- curr |= curr >> next;
- }
- return ++curr;
- }
- /**
- * @brief Fast module utility function (powers of two only).
- * @param value A value for which to calculate the modulus.
- * @param mod _Modulus_, it must be a power of two.
- * @return The common remainder.
- */
- [[nodiscard]] inline constexpr std::size_t fast_mod(const std::size_t value, const std::size_t mod) ENTT_NOEXCEPT {
- ENTT_ASSERT(is_power_of_two(mod), "Value must be a power of two");
- return value & (mod - 1u);
- }
- /**
- * @brief Deleter for allocator-aware unique pointers (waiting for C++20).
- * @tparam Args Types of arguments to use to construct the object.
- */
- 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.
- */
- allocation_deleter(const allocator_type &alloc)
- : Allocator{alloc} {}
- /**
- * @brief Destroys the pointed object and deallocates its memory.
- * @param ptr A valid pointer to an object of the given type.
- */
- void operator()(pointer ptr) {
- using alloc_traits = typename 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>
- 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
- * Internal details not to be documented.
- */
- 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) ENTT_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) ENTT_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) ENTT_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) ENTT_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) ENTT_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) ENTT_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
- /**
- * Internal details not to be documented.
- * @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) ENTT_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([&](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 <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.
- * @tparam The size of the type if `sizeof` accepts it, 0 otherwise.
- */
- 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))>>
- : 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 Type First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<std::size_t Index, typename Type, typename... Other>
- struct type_list_element<Index, type_list<Type, Other...>>
- : type_list_element<Index - 1u, type_list<Other...>> {};
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam Type First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<typename Type, typename... Other>
- struct type_list_element<0u, type_list<Type, Other...>> {
- /*! @brief Searched type. */
- using type = Type;
- };
- /**
- * @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 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;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename>
- struct type_list_unique;
- /**
- * @brief Removes duplicates types from a type list.
- * @tparam Type One of the types provided by the given type list.
- * @tparam Other The other types provided by the given type list.
- */
- template<typename Type, typename... Other>
- struct type_list_unique<type_list<Type, Other...>> {
- /*! @brief A type list without duplicate types. */
- using type = std::conditional_t<
- (std::is_same_v<Type, Other> || ...),
- typename type_list_unique<type_list<Other...>>::type,
- type_list_cat_t<type_list<Type>, typename type_list_unique<type_list<Other...>>::type>>;
- };
- /*! @brief Removes duplicates types from a type list. */
- template<>
- struct type_list_unique<type_list<>> {
- /*! @brief A type list without duplicate types. */
- using type = type_list<>;
- };
- /**
- * @brief Helper type.
- * @tparam Type A type list.
- */
- template<typename Type>
- using type_list_unique_t = typename type_list_unique<Type>::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::disjunction<std::is_same<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 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 value. */
- static constexpr auto value = Value;
- };
- /**
- * @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 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 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
- * Internal details not to be documented.
- */
- 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
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /*! @copydoc is_iterator */
- template<typename Type>
- struct is_iterator<Type, std::enable_if_t<!std::is_same_v<std::remove_const_t<std::remove_pointer_t<Type>>, void>>>
- : 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::conjunction<std::is_empty<Type>, std::negation<std::is_final<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;
- /**
- * @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, typename = void>
- struct is_equality_comparable: std::false_type {};
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- 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 Type, std::size_t... Index>
- [[nodiscard]] constexpr bool unpack_maybe_equality_comparable(std::index_sequence<Index...>) {
- return (is_equality_comparable<std::tuple_element_t<Index, Type>>::value && ...);
- }
- template<typename>
- [[nodiscard]] constexpr bool maybe_equality_comparable(choice_t<0>) {
- return true;
- }
- template<typename Type>
- [[nodiscard]] constexpr auto maybe_equality_comparable(choice_t<1>) -> decltype(std::declval<typename Type::value_type>(), bool{}) {
- if constexpr(is_iterator_v<Type>) {
- return true;
- } else if constexpr(std::is_same_v<typename Type::value_type, Type>) {
- return maybe_equality_comparable<Type>(choice<0>);
- } else {
- return is_equality_comparable<typename Type::value_type>::value;
- }
- }
- template<typename Type>
- [[nodiscard]] constexpr std::enable_if_t<is_complete_v<std::tuple_size<std::remove_const_t<Type>>>, bool> maybe_equality_comparable(choice_t<2>) {
- if constexpr(has_tuple_size_value<Type>::value) {
- return unpack_maybe_equality_comparable<Type>(std::make_index_sequence<std::tuple_size<Type>::value>{});
- } else {
- return maybe_equality_comparable<Type>(choice<1>);
- }
- }
- } // namespace internal
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /*! @copydoc is_equality_comparable */
- template<typename Type>
- struct is_equality_comparable<Type, std::void_t<decltype(std::declval<Type>() == std::declval<Type>())>>
- : std::bool_constant<internal::maybe_equality_comparable<Type>(choice<2>)> {};
- /**
- * @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 = std::add_const_t<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;
- } // namespace entt
- #endif
- // #include "fwd.hpp"
- #ifndef ENTT_CONTAINER_FWD_HPP
- #define ENTT_CONTAINER_FWD_HPP
- #include <functional>
- #include <memory>
- namespace entt {
- template<
- typename Key,
- typename Type,
- typename = std::hash<Key>,
- typename = std::equal_to<Key>,
- typename = std::allocator<std::pair<const Key, Type>>>
- class dense_map;
- template<
- typename Type,
- typename = std::hash<Type>,
- typename = std::equal_to<Type>,
- typename = std::allocator<Type>>
- class dense_set;
- } // namespace entt
- #endif
- namespace entt {
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- namespace internal {
- 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;
- dense_map_iterator() ENTT_NOEXCEPT
- : it{} {}
- dense_map_iterator(const It iter) ENTT_NOEXCEPT
- : it{iter} {}
- template<typename Other, typename = std::enable_if_t<!std::is_same_v<It, Other> && std::is_constructible_v<It, Other>>>
- dense_map_iterator(const dense_map_iterator<Other> &other) ENTT_NOEXCEPT
- : it{other.it} {}
- dense_map_iterator &operator++() ENTT_NOEXCEPT {
- return ++it, *this;
- }
- dense_map_iterator operator++(int) ENTT_NOEXCEPT {
- dense_map_iterator orig = *this;
- return ++(*this), orig;
- }
- dense_map_iterator &operator--() ENTT_NOEXCEPT {
- return --it, *this;
- }
- dense_map_iterator operator--(int) ENTT_NOEXCEPT {
- dense_map_iterator orig = *this;
- return operator--(), orig;
- }
- dense_map_iterator &operator+=(const difference_type value) ENTT_NOEXCEPT {
- it += value;
- return *this;
- }
- dense_map_iterator operator+(const difference_type value) const ENTT_NOEXCEPT {
- dense_map_iterator copy = *this;
- return (copy += value);
- }
- dense_map_iterator &operator-=(const difference_type value) ENTT_NOEXCEPT {
- return (*this += -value);
- }
- dense_map_iterator operator-(const difference_type value) const ENTT_NOEXCEPT {
- return (*this + -value);
- }
- [[nodiscard]] reference operator[](const difference_type value) const ENTT_NOEXCEPT {
- return {it[value].element.first, it[value].element.second};
- }
- [[nodiscard]] pointer operator->() const ENTT_NOEXCEPT {
- return operator*();
- }
- [[nodiscard]] reference operator*() const ENTT_NOEXCEPT {
- return {it->element.first, it->element.second};
- }
- template<typename ILhs, typename IRhs>
- friend std::ptrdiff_t operator-(const dense_map_iterator<ILhs> &, const dense_map_iterator<IRhs> &) ENTT_NOEXCEPT;
- template<typename ILhs, typename IRhs>
- friend bool operator==(const dense_map_iterator<ILhs> &, const dense_map_iterator<IRhs> &) ENTT_NOEXCEPT;
- template<typename ILhs, typename IRhs>
- friend bool operator<(const dense_map_iterator<ILhs> &, const dense_map_iterator<IRhs> &) ENTT_NOEXCEPT;
- private:
- It it;
- };
- template<typename ILhs, typename IRhs>
- [[nodiscard]] std::ptrdiff_t operator-(const dense_map_iterator<ILhs> &lhs, const dense_map_iterator<IRhs> &rhs) ENTT_NOEXCEPT {
- return lhs.it - rhs.it;
- }
- template<typename ILhs, typename IRhs>
- [[nodiscard]] bool operator==(const dense_map_iterator<ILhs> &lhs, const dense_map_iterator<IRhs> &rhs) ENTT_NOEXCEPT {
- return lhs.it == rhs.it;
- }
- template<typename ILhs, typename IRhs>
- [[nodiscard]] bool operator!=(const dense_map_iterator<ILhs> &lhs, const dense_map_iterator<IRhs> &rhs) ENTT_NOEXCEPT {
- return !(lhs == rhs);
- }
- template<typename ILhs, typename IRhs>
- [[nodiscard]] bool operator<(const dense_map_iterator<ILhs> &lhs, const dense_map_iterator<IRhs> &rhs) ENTT_NOEXCEPT {
- return lhs.it < rhs.it;
- }
- template<typename ILhs, typename IRhs>
- [[nodiscard]] bool operator>(const dense_map_iterator<ILhs> &lhs, const dense_map_iterator<IRhs> &rhs) ENTT_NOEXCEPT {
- return rhs < lhs;
- }
- template<typename ILhs, typename IRhs>
- [[nodiscard]] bool operator<=(const dense_map_iterator<ILhs> &lhs, const dense_map_iterator<IRhs> &rhs) ENTT_NOEXCEPT {
- return !(lhs > rhs);
- }
- template<typename ILhs, typename IRhs>
- [[nodiscard]] bool operator>=(const dense_map_iterator<ILhs> &lhs, const dense_map_iterator<IRhs> &rhs) ENTT_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;
- dense_map_local_iterator() ENTT_NOEXCEPT
- : it{},
- offset{} {}
- dense_map_local_iterator(It iter, const std::size_t pos) ENTT_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>>>
- dense_map_local_iterator(const dense_map_local_iterator<Other> &other) ENTT_NOEXCEPT
- : it{other.it},
- offset{other.offset} {}
- dense_map_local_iterator &operator++() ENTT_NOEXCEPT {
- return offset = it[offset].next, *this;
- }
- dense_map_local_iterator operator++(int) ENTT_NOEXCEPT {
- dense_map_local_iterator orig = *this;
- return ++(*this), orig;
- }
- [[nodiscard]] pointer operator->() const ENTT_NOEXCEPT {
- return operator*();
- }
- [[nodiscard]] reference operator*() const ENTT_NOEXCEPT {
- return {it[offset].element.first, it[offset].element.second};
- }
- [[nodiscard]] std::size_t index() const ENTT_NOEXCEPT {
- return offset;
- }
- private:
- It it;
- std::size_t offset;
- };
- template<typename ILhs, typename IRhs>
- [[nodiscard]] bool operator==(const dense_map_local_iterator<ILhs> &lhs, const dense_map_local_iterator<IRhs> &rhs) ENTT_NOEXCEPT {
- return lhs.index() == rhs.index();
- }
- template<typename ILhs, typename IRhs>
- [[nodiscard]] bool operator!=(const dense_map_local_iterator<ILhs> &lhs, const dense_map_local_iterator<IRhs> &rhs) ENTT_NOEXCEPT {
- return !(lhs == rhs);
- }
- } // namespace internal
- /**
- * Internal details not to be documented.
- * @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;
- using node_type = internal::dense_map_node<Key, Type>;
- using alloc_traits = typename 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 ENTT_NOEXCEPT {
- return fast_mod(sparse.second()(key), bucket_count());
- }
- template<typename Other>
- [[nodiscard]] auto constrained_find(const Other &key, std::size_t bucket) {
- for(auto it = begin(bucket), last = end(bucket); it != last; ++it) {
- if(packed.second()(it->first, key)) {
- return begin() + static_cast<typename iterator::difference_type>(it.index());
- }
- }
- return end();
- }
- template<typename Other>
- [[nodiscard]] auto constrained_find(const Other &key, std::size_t bucket) const {
- for(auto it = cbegin(bucket), last = cend(bucket); it != last; ++it) {
- if(packed.second()(it->first, key)) {
- return cbegin() + static_cast<typename iterator::difference_type>(it.index());
- }
- }
- 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) {
- packed.first()[pos] = std::move(packed.first().back());
- size_type *curr = sparse.first().data() + key_to_bucket(packed.first().back().element.first);
- for(; *curr != last; curr = &packed.first()[*curr].next) {}
- *curr = pos;
- }
- packed.first().pop_back();
- }
- void rehash_if_required() {
- if(size() > (bucket_count() * max_load_factor())) {
- rehash(bucket_count() * 2u);
- }
- }
- public:
- /*! @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 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 Allocator type. */
- using allocator_type = Allocator;
- /*! @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 bucket_count Minimal number of buckets.
- * @param allocator The allocator to use.
- */
- dense_map(const size_type bucket_count, const allocator_type &allocator)
- : dense_map{bucket_count, hasher{}, key_equal{}, allocator} {}
- /**
- * @brief Constructs an empty container with a given allocator, hash
- * function and user supplied minimal number of buckets.
- * @param bucket_count Minimal number of buckets.
- * @param hash Hash function to use.
- * @param allocator The allocator to use.
- */
- dense_map(const size_type bucket_count, const hasher &hash, const allocator_type &allocator)
- : dense_map{bucket_count, 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 bucket_count 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 bucket_count, const hasher &hash = hasher{}, const key_equal &equal = key_equal{}, const allocator_type &allocator = allocator_type{})
- : sparse{allocator, hash},
- packed{allocator, equal},
- threshold{default_threshold} {
- rehash(bucket_count);
- }
- /*! @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 &&) = 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 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 &&) = default;
- /**
- * @brief Returns the associated allocator.
- * @return The associated allocator.
- */
- [[nodiscard]] constexpr allocator_type get_allocator() const ENTT_NOEXCEPT {
- return sparse.first().get_allocator();
- }
- /**
- * @brief Returns an iterator to the beginning.
- *
- * The returned iterator points to the first instance of the internal array.
- * 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 ENTT_NOEXCEPT {
- return packed.first().begin();
- }
- /*! @copydoc cbegin */
- [[nodiscard]] const_iterator begin() const ENTT_NOEXCEPT {
- return cbegin();
- }
- /*! @copydoc begin */
- [[nodiscard]] iterator begin() ENTT_NOEXCEPT {
- return packed.first().begin();
- }
- /**
- * @brief Returns an iterator to the end.
- *
- * The returned iterator points to the element following the last instance
- * of the internal array. Attempting to dereference the returned iterator
- * results in undefined behavior.
- *
- * @return An iterator to the element following the last instance of the
- * internal array.
- */
- [[nodiscard]] const_iterator cend() const ENTT_NOEXCEPT {
- return packed.first().end();
- }
- /*! @copydoc cend */
- [[nodiscard]] const_iterator end() const ENTT_NOEXCEPT {
- return cend();
- }
- /*! @copydoc end */
- [[nodiscard]] iterator end() ENTT_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 ENTT_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 ENTT_NOEXCEPT {
- return packed.first().size();
- }
- /*! @brief Clears the container. */
- void clear() ENTT_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()[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().data() + key_to_bucket(key); *curr != (std::numeric_limits<size_type>::max)(); 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 Exchanges the contents with those of a given container.
- * @param other Container to exchange the content with.
- */
- void swap(dense_map &other) {
- using std::swap;
- swap(sparse, other.sparse);
- swap(packed, other.packed);
- swap(threshold, other.threshold);
- }
- /**
- * @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 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 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
- * 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 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 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 {packed.first().begin(), (std::numeric_limits<size_type>::max)()};
- }
- /**
- * @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([[maybe_unused]] 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 {packed.first().begin(), (std::numeric_limits<size_type>::max)()};
- }
- /**
- * @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 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 count New number of buckets.
- */
- void rehash(const size_type count) {
- auto value = (std::max)(count, minimum_capacity);
- value = (std::max)(value, static_cast<size_type>(size() / max_load_factor()));
- if(const auto sz = next_power_of_two(value); sz != bucket_count()) {
- sparse.first().resize(sz);
- std::fill(sparse.first().begin(), sparse.first().end(), (std::numeric_limits<size_type>::max)());
- 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 count New number of elements.
- */
- void reserve(const size_type count) {
- packed.first().reserve(count);
- rehash(static_cast<size_type>(std::ceil(count / 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;
- };
- } // namespace entt
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- 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
- /**
- * Internal details not to be documented.
- * @endcond
- */
- #endif
- // #include "../container/dense_set.hpp"
- #ifndef ENTT_CONTAINER_DENSE_SET_HPP
- #define ENTT_CONTAINER_DENSE_SET_HPP
- #include <algorithm>
- #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/compressed_pair.hpp"
- // #include "../core/memory.hpp"
- // #include "../core/type_traits.hpp"
- // #include "fwd.hpp"
- namespace entt {
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- namespace internal {
- 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;
- dense_set_iterator() ENTT_NOEXCEPT
- : it{} {}
- dense_set_iterator(const It iter) ENTT_NOEXCEPT
- : it{iter} {}
- template<typename Other, typename = std::enable_if_t<!std::is_same_v<It, Other> && std::is_constructible_v<It, Other>>>
- dense_set_iterator(const dense_set_iterator<Other> &other) ENTT_NOEXCEPT
- : it{other.it} {}
- dense_set_iterator &operator++() ENTT_NOEXCEPT {
- return ++it, *this;
- }
- dense_set_iterator operator++(int) ENTT_NOEXCEPT {
- dense_set_iterator orig = *this;
- return ++(*this), orig;
- }
- dense_set_iterator &operator--() ENTT_NOEXCEPT {
- return --it, *this;
- }
- dense_set_iterator operator--(int) ENTT_NOEXCEPT {
- dense_set_iterator orig = *this;
- return operator--(), orig;
- }
- dense_set_iterator &operator+=(const difference_type value) ENTT_NOEXCEPT {
- it += value;
- return *this;
- }
- dense_set_iterator operator+(const difference_type value) const ENTT_NOEXCEPT {
- dense_set_iterator copy = *this;
- return (copy += value);
- }
- dense_set_iterator &operator-=(const difference_type value) ENTT_NOEXCEPT {
- return (*this += -value);
- }
- dense_set_iterator operator-(const difference_type value) const ENTT_NOEXCEPT {
- return (*this + -value);
- }
- [[nodiscard]] reference operator[](const difference_type value) const ENTT_NOEXCEPT {
- return it[value].second;
- }
- [[nodiscard]] pointer operator->() const ENTT_NOEXCEPT {
- return std::addressof(it->second);
- }
- [[nodiscard]] reference operator*() const ENTT_NOEXCEPT {
- return *operator->();
- }
- template<typename ILhs, typename IRhs>
- friend std::ptrdiff_t operator-(const dense_set_iterator<ILhs> &, const dense_set_iterator<IRhs> &) ENTT_NOEXCEPT;
- template<typename ILhs, typename IRhs>
- friend bool operator==(const dense_set_iterator<ILhs> &, const dense_set_iterator<IRhs> &) ENTT_NOEXCEPT;
- template<typename ILhs, typename IRhs>
- friend bool operator<(const dense_set_iterator<ILhs> &, const dense_set_iterator<IRhs> &) ENTT_NOEXCEPT;
- private:
- It it;
- };
- template<typename ILhs, typename IRhs>
- [[nodiscard]] std::ptrdiff_t operator-(const dense_set_iterator<ILhs> &lhs, const dense_set_iterator<IRhs> &rhs) ENTT_NOEXCEPT {
- return lhs.it - rhs.it;
- }
- template<typename ILhs, typename IRhs>
- [[nodiscard]] bool operator==(const dense_set_iterator<ILhs> &lhs, const dense_set_iterator<IRhs> &rhs) ENTT_NOEXCEPT {
- return lhs.it == rhs.it;
- }
- template<typename ILhs, typename IRhs>
- [[nodiscard]] bool operator!=(const dense_set_iterator<ILhs> &lhs, const dense_set_iterator<IRhs> &rhs) ENTT_NOEXCEPT {
- return !(lhs == rhs);
- }
- template<typename ILhs, typename IRhs>
- [[nodiscard]] bool operator<(const dense_set_iterator<ILhs> &lhs, const dense_set_iterator<IRhs> &rhs) ENTT_NOEXCEPT {
- return lhs.it < rhs.it;
- }
- template<typename ILhs, typename IRhs>
- [[nodiscard]] bool operator>(const dense_set_iterator<ILhs> &lhs, const dense_set_iterator<IRhs> &rhs) ENTT_NOEXCEPT {
- return rhs < lhs;
- }
- template<typename ILhs, typename IRhs>
- [[nodiscard]] bool operator<=(const dense_set_iterator<ILhs> &lhs, const dense_set_iterator<IRhs> &rhs) ENTT_NOEXCEPT {
- return !(lhs > rhs);
- }
- template<typename ILhs, typename IRhs>
- [[nodiscard]] bool operator>=(const dense_set_iterator<ILhs> &lhs, const dense_set_iterator<IRhs> &rhs) ENTT_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;
- dense_set_local_iterator() ENTT_NOEXCEPT
- : it{},
- offset{} {}
- dense_set_local_iterator(It iter, const std::size_t pos) ENTT_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>>>
- dense_set_local_iterator(const dense_set_local_iterator<Other> &other) ENTT_NOEXCEPT
- : it{other.it},
- offset{other.offset} {}
- dense_set_local_iterator &operator++() ENTT_NOEXCEPT {
- return offset = it[offset].first, *this;
- }
- dense_set_local_iterator operator++(int) ENTT_NOEXCEPT {
- dense_set_local_iterator orig = *this;
- return ++(*this), orig;
- }
- [[nodiscard]] pointer operator->() const ENTT_NOEXCEPT {
- return std::addressof(it[offset].second);
- }
- [[nodiscard]] reference operator*() const ENTT_NOEXCEPT {
- return *operator->();
- }
- [[nodiscard]] std::size_t index() const ENTT_NOEXCEPT {
- return offset;
- }
- private:
- It it;
- std::size_t offset;
- };
- template<typename ILhs, typename IRhs>
- [[nodiscard]] bool operator==(const dense_set_local_iterator<ILhs> &lhs, const dense_set_local_iterator<IRhs> &rhs) ENTT_NOEXCEPT {
- return lhs.index() == rhs.index();
- }
- template<typename ILhs, typename IRhs>
- [[nodiscard]] bool operator!=(const dense_set_local_iterator<ILhs> &lhs, const dense_set_local_iterator<IRhs> &rhs) ENTT_NOEXCEPT {
- return !(lhs == rhs);
- }
- } // namespace internal
- /**
- * Internal details not to be documented.
- * @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;
- 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 ENTT_NOEXCEPT {
- return fast_mod(sparse.second()(value), bucket_count());
- }
- template<typename Other>
- [[nodiscard]] auto constrained_find(const Other &value, std::size_t bucket) {
- for(auto it = begin(bucket), last = end(bucket); it != last; ++it) {
- if(packed.second()(*it, value)) {
- return begin() + static_cast<typename iterator::difference_type>(it.index());
- }
- }
- return end();
- }
- template<typename Other>
- [[nodiscard]] auto constrained_find(const Other &value, std::size_t bucket) const {
- for(auto it = cbegin(bucket), last = cend(bucket); it != last; ++it) {
- if(packed.second()(*it, value)) {
- return cbegin() + static_cast<typename iterator::difference_type>(it.index());
- }
- }
- 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) {
- packed.first()[pos] = std::move(packed.first().back());
- size_type *curr = sparse.first().data() + value_to_bucket(packed.first().back().second);
- for(; *curr != last; curr = &packed.first()[*curr].first) {}
- *curr = pos;
- }
- packed.first().pop_back();
- }
- void rehash_if_required() {
- if(size() > (bucket_count() * max_load_factor())) {
- rehash(bucket_count() * 2u);
- }
- }
- public:
- /*! @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 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 Allocator type. */
- using allocator_type = Allocator;
- /*! @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 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 bucket_count Minimal number of buckets.
- * @param allocator The allocator to use.
- */
- dense_set(const size_type bucket_count, const allocator_type &allocator)
- : dense_set{bucket_count, hasher{}, key_equal{}, allocator} {}
- /**
- * @brief Constructs an empty container with a given allocator, hash
- * function and user supplied minimal number of buckets.
- * @param bucket_count Minimal number of buckets.
- * @param hash Hash function to use.
- * @param allocator The allocator to use.
- */
- dense_set(const size_type bucket_count, const hasher &hash, const allocator_type &allocator)
- : dense_set{bucket_count, 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 bucket_count 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 bucket_count, const hasher &hash = hasher{}, const key_equal &equal = key_equal{}, const allocator_type &allocator = allocator_type{})
- : sparse{allocator, hash},
- packed{allocator, equal},
- threshold{default_threshold} {
- rehash(bucket_count);
- }
- /*! @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 &&) = 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 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 &&) = default;
- /**
- * @brief Returns the associated allocator.
- * @return The associated allocator.
- */
- [[nodiscard]] constexpr allocator_type get_allocator() const ENTT_NOEXCEPT {
- return sparse.first().get_allocator();
- }
- /**
- * @brief Returns an iterator to the beginning.
- *
- * The returned iterator points to the first instance of the internal array.
- * 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 ENTT_NOEXCEPT {
- return packed.first().begin();
- }
- /*! @copydoc cbegin */
- [[nodiscard]] const_iterator begin() const ENTT_NOEXCEPT {
- return cbegin();
- }
- /*! @copydoc begin */
- [[nodiscard]] iterator begin() ENTT_NOEXCEPT {
- return packed.first().begin();
- }
- /**
- * @brief Returns an iterator to the end.
- *
- * The returned iterator points to the element following the last instance
- * of the internal array. Attempting to dereference the returned iterator
- * results in undefined behavior.
- *
- * @return An iterator to the element following the last instance of the
- * internal array.
- */
- [[nodiscard]] const_iterator cend() const ENTT_NOEXCEPT {
- return packed.first().end();
- }
- /*! @copydoc cend */
- [[nodiscard]] const_iterator end() const ENTT_NOEXCEPT {
- return cend();
- }
- /*! @copydoc end */
- [[nodiscard]] iterator end() ENTT_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 ENTT_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 ENTT_NOEXCEPT {
- return packed.first().size();
- }
- /*! @brief Clears the container. */
- void clear() ENTT_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::remove_cv_t<std::remove_reference_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()[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().data() + value_to_bucket(value); *curr != (std::numeric_limits<size_type>::max)(); 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 Exchanges the contents with those of a given container.
- * @param other Container to exchange the content with.
- */
- void swap(dense_set &other) {
- using std::swap;
- swap(sparse, other.sparse);
- swap(packed, other.packed);
- swap(threshold, other.threshold);
- }
- /**
- * @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 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 {packed.first().begin(), (std::numeric_limits<size_type>::max)()};
- }
- /**
- * @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([[maybe_unused]] 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 {packed.first().begin(), (std::numeric_limits<size_type>::max)()};
- }
- /**
- * @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 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 count New number of buckets.
- */
- void rehash(const size_type count) {
- auto value = (std::max)(count, minimum_capacity);
- value = (std::max)(value, static_cast<size_type>(size() / max_load_factor()));
- if(const auto sz = next_power_of_two(value); sz != bucket_count()) {
- sparse.first().resize(sz);
- std::fill(sparse.first().begin(), sparse.first().end(), (std::numeric_limits<size_type>::max)());
- 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 count New number of elements.
- */
- void reserve(const size_type count) {
- packed.first().reserve(count);
- rehash(static_cast<size_type>(std::ceil(count / 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;
- };
- } // namespace entt
- #endif
- // #include "meta.hpp"
- #ifndef ENTT_META_META_HPP
- #define ENTT_META_META_HPP
- #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
- #define ENTT_STR(arg) #arg
- #define ENTT_XSTR(arg) ENTT_STR(arg)
- #endif
- #define ENTT_VERSION_MAJOR 3
- #define ENTT_VERSION_MINOR 10
- #define ENTT_VERSION_PATCH 3
- #define ENTT_VERSION \
- ENTT_XSTR(ENTT_VERSION_MAJOR) \
- "." ENTT_XSTR(ENTT_VERSION_MINOR) "." ENTT_XSTR(ENTT_VERSION_PATCH)
- #endif
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #ifndef ENTT_NOEXCEPT
- # define ENTT_NOEXCEPT noexcept
- # define ENTT_NOEXCEPT_IF(expr) noexcept(expr)
- # else
- # define ENTT_NOEXCEPT_IF(...)
- #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
- #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(...) (void(0))
- #elif !defined ENTT_ASSERT
- # include <cassert>
- # define ENTT_ASSERT(condition, ...) assert(condition)
- #endif
- #ifdef ENTT_NO_ETO
- # define ENTT_IGNORE_IF_EMPTY false
- #else
- # define ENTT_IGNORE_IF_EMPTY true
- #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
- #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
- #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
- #define ENTT_STR(arg) #arg
- #define ENTT_XSTR(arg) ENTT_STR(arg)
- #endif
- #define ENTT_VERSION_MAJOR 3
- #define ENTT_VERSION_MINOR 10
- #define ENTT_VERSION_PATCH 3
- #define ENTT_VERSION \
- ENTT_XSTR(ENTT_VERSION_MAJOR) \
- "." ENTT_XSTR(ENTT_VERSION_MINOR) "." ENTT_XSTR(ENTT_VERSION_PATCH)
- #endif
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #ifndef ENTT_NOEXCEPT
- # define ENTT_NOEXCEPT noexcept
- # define ENTT_NOEXCEPT_IF(expr) noexcept(expr)
- # else
- # define ENTT_NOEXCEPT_IF(...)
- #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
- #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(...) (void(0))
- #elif !defined ENTT_ASSERT
- # include <cassert>
- # define ENTT_ASSERT(condition, ...) assert(condition)
- #endif
- #ifdef ENTT_NO_ETO
- # define ENTT_IGNORE_IF_EMPTY false
- #else
- # define ENTT_IGNORE_IF_EMPTY true
- #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
- #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
- #endif
- // #include "../core/utility.hpp"
- #ifndef ENTT_CORE_UTILITY_HPP
- #define ENTT_CORE_UTILITY_HPP
- #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
- #define ENTT_STR(arg) #arg
- #define ENTT_XSTR(arg) ENTT_STR(arg)
- #endif
- #define ENTT_VERSION_MAJOR 3
- #define ENTT_VERSION_MINOR 10
- #define ENTT_VERSION_PATCH 3
- #define ENTT_VERSION \
- ENTT_XSTR(ENTT_VERSION_MAJOR) \
- "." ENTT_XSTR(ENTT_VERSION_MINOR) "." ENTT_XSTR(ENTT_VERSION_PATCH)
- #endif
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #ifndef ENTT_NOEXCEPT
- # define ENTT_NOEXCEPT noexcept
- # define ENTT_NOEXCEPT_IF(expr) noexcept(expr)
- # else
- # define ENTT_NOEXCEPT_IF(...)
- #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
- #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(...) (void(0))
- #elif !defined ENTT_ASSERT
- # include <cassert>
- # define ENTT_ASSERT(condition, ...) assert(condition)
- #endif
- #ifdef ENTT_NO_ETO
- # define ENTT_IGNORE_IF_EMPTY false
- #else
- # define ENTT_IGNORE_IF_EMPTY true
- #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
- #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
- #endif
- 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<class Type>
- [[nodiscard]] constexpr Type &&operator()(Type &&value) const ENTT_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) ENTT_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) ENTT_NOEXCEPT {
- return func;
- }
- /**
- * @brief Helper type for visitors.
- * @tparam Func Types of function objects.
- */
- template<class... Func>
- struct overloaded: Func... {
- using Func::operator()...;
- };
- /**
- * @brief Deduction guide.
- * @tparam Func Types of function objects.
- */
- template<class... Func>
- overloaded(Func...) -> overloaded<Func...>;
- /**
- * @brief Basic implementation of a y-combinator.
- * @tparam Func Type of a potentially recursive function.
- */
- template<class Func>
- struct y_combinator {
- /**
- * @brief Constructs a y-combinator from a given function.
- * @param recursive A potentially recursive function.
- */
- y_combinator(Func recursive)
- : 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<class... Args>
- decltype(auto) operator()(Args &&...args) const {
- return func(*this, std::forward<Args>(args)...);
- }
- /*! @copydoc operator()() */
- template<class... Args>
- decltype(auto) operator()(Args &&...args) {
- return func(*this, std::forward<Args>(args)...);
- }
- private:
- Func func;
- };
- } // namespace entt
- #endif
- // #include "fwd.hpp"
- #ifndef ENTT_CORE_FWD_HPP
- #define ENTT_CORE_FWD_HPP
- #include <cstdint>
- #include <type_traits>
- // #include "../config/config.h"
- namespace entt {
- template<std::size_t Len = sizeof(double[2]), std::size_t = alignof(typename std::aligned_storage_t<Len + !Len>)>
- 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<>;
- } // 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 "../core/attribute.h"
- #ifndef ENTT_CORE_ATTRIBUTE_H
- #define ENTT_CORE_ATTRIBUTE_H
- #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
- #endif
- // #include "fwd.hpp"
- // #include "hashed_string.hpp"
- #ifndef ENTT_CORE_HASHED_STRING_HPP
- #define ENTT_CORE_HASHED_STRING_HPP
- #include <cstddef>
- #include <cstdint>
- // #include "../config/config.h"
- // #include "fwd.hpp"
- namespace entt {
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- namespace internal {
- template<typename>
- struct fnv1a_traits;
- template<>
- struct fnv1a_traits<std::uint32_t> {
- using type = std::uint32_t;
- static constexpr std::uint32_t offset = 2166136261;
- static constexpr std::uint32_t prime = 16777619;
- };
- template<>
- struct fnv1a_traits<std::uint64_t> {
- using type = std::uint64_t;
- static constexpr std::uint64_t offset = 14695981039346656037ull;
- static constexpr std::uint64_t 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;
- size_type length;
- hash_type hash;
- };
- } // namespace internal
- /**
- * Internal details not to be documented.
- * @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 hs_traits = internal::fnv1a_traits<id_type>;
- struct const_wrapper {
- // non-explicit constructor on purpose
- constexpr const_wrapper(const Char *str) ENTT_NOEXCEPT: repr{str} {}
- const Char *repr;
- };
- // Fowler–Noll–Vo hash function v. 1a - the good
- [[nodiscard]] static constexpr auto helper(const Char *str) ENTT_NOEXCEPT {
- base_type base{str, 0u, hs_traits::offset};
- for(; str[base.length]; ++base.length) {
- base.hash = (base.hash ^ static_cast<hs_traits::type>(str[base.length])) * hs_traits::prime;
- }
- return base;
- }
- // Fowler–Noll–Vo hash function v. 1a - the good
- [[nodiscard]] static constexpr auto helper(const Char *str, const std::size_t len) ENTT_NOEXCEPT {
- base_type base{str, len, hs_traits::offset};
- for(size_type pos{}; pos < len; ++pos) {
- base.hash = (base.hash ^ static_cast<hs_traits::type>(str[pos])) * hs_traits::prime;
- }
- return base;
- }
- 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) ENTT_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>
- [[nodiscard]] static constexpr hash_type value(const value_type (&str)[N]) ENTT_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) ENTT_NOEXCEPT {
- return basic_hashed_string{wrapper};
- }
- /*! @brief Constructs an empty hashed string. */
- constexpr basic_hashed_string() ENTT_NOEXCEPT
- : base_type{} {}
- /**
- * @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) ENTT_NOEXCEPT
- : base_type{helper(str, len)} {}
- /**
- * @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>
- constexpr basic_hashed_string(const value_type (&str)[N]) ENTT_NOEXCEPT
- : base_type{helper(str)} {}
- /**
- * @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) ENTT_NOEXCEPT
- : base_type{helper(wrapper.repr)} {}
- /**
- * @brief Returns the size a hashed string.
- * @return The size of the hashed string.
- */
- [[nodiscard]] constexpr size_type size() const ENTT_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 ENTT_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 ENTT_NOEXCEPT {
- return base_type::hash;
- }
- /*! @copydoc data */
- [[nodiscard]] constexpr operator const value_type *() const ENTT_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 ENTT_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, const 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>
- 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) ENTT_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) ENTT_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) ENTT_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) ENTT_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) ENTT_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) ENTT_NOEXCEPT {
- return !(lhs < rhs);
- }
- /*! @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>;
- inline namespace literals {
- /**
- * @brief User defined literal for hashed strings.
- * @param str The literal without its suffix.
- * @return A properly initialized hashed string.
- */
- [[nodiscard]] constexpr hashed_string operator"" _hs(const char *str, std::size_t) ENTT_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]] constexpr hashed_wstring operator"" _hws(const wchar_t *str, std::size_t) ENTT_NOEXCEPT {
- return hashed_wstring{str};
- }
- } // namespace literals
- } // namespace entt
- #endif
- namespace entt {
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- namespace internal {
- struct ENTT_API type_index final {
- [[nodiscard]] static id_type next() ENTT_NOEXCEPT {
- static ENTT_MAYBE_ATOMIC(id_type) value{};
- return value++;
- }
- };
- template<typename Type>
- [[nodiscard]] constexpr auto stripped_type_name() ENTT_NOEXCEPT {
- #if defined ENTT_PRETTY_FUNCTION
- std::string_view pretty_function{ENTT_PRETTY_FUNCTION};
- auto first = pretty_function.find_first_not_of(' ', pretty_function.find_first_of(ENTT_PRETTY_FUNCTION_PREFIX) + 1);
- auto value = pretty_function.substr(first, pretty_function.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]] static constexpr std::string_view type_name(int) ENTT_NOEXCEPT {
- constexpr auto value = stripped_type_name<Type>();
- return value;
- }
- template<typename Type>
- [[nodiscard]] static std::string_view type_name(char) ENTT_NOEXCEPT {
- static const auto value = stripped_type_name<Type>();
- return value;
- }
- template<typename Type, auto = stripped_type_name<Type>().find_first_of('.')>
- [[nodiscard]] static constexpr id_type type_hash(int) ENTT_NOEXCEPT {
- constexpr auto stripped = stripped_type_name<Type>();
- constexpr auto value = hashed_string::value(stripped.data(), stripped.size());
- return value;
- }
- template<typename Type>
- [[nodiscard]] static id_type type_hash(char) ENTT_NOEXCEPT {
- static const auto value = [](const auto stripped) {
- return hashed_string::value(stripped.data(), stripped.size());
- }(stripped_type_name<Type>());
- return value;
- }
- } // namespace internal
- /**
- * Internal details not to be documented.
- * @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() ENTT_NOEXCEPT {
- static const id_type value = internal::type_index::next();
- return value;
- }
- /*! @copydoc value */
- [[nodiscard]] constexpr operator id_type() const ENTT_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() ENTT_NOEXCEPT {
- return internal::type_hash<Type>(0);
- #else
- [[nodiscard]] static constexpr id_type value() ENTT_NOEXCEPT {
- return type_index<Type>::value();
- #endif
- }
- /*! @copydoc value */
- [[nodiscard]] constexpr operator id_type() const ENTT_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() ENTT_NOEXCEPT {
- return internal::type_name<Type>(0);
- }
- /*! @copydoc value */
- [[nodiscard]] constexpr operator std::string_view() const ENTT_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>
- constexpr type_info(std::in_place_type_t<Type>) ENTT_NOEXCEPT
- : seq{type_index<std::remove_cv_t<std::remove_reference_t<Type>>>::value()},
- identifier{type_hash<std::remove_cv_t<std::remove_reference_t<Type>>>::value()},
- alias{type_name<std::remove_cv_t<std::remove_reference_t<Type>>>::value()} {}
- /**
- * @brief Type index.
- * @return Type index.
- */
- [[nodiscard]] constexpr id_type index() const ENTT_NOEXCEPT {
- return seq;
- }
- /**
- * @brief Type hash.
- * @return Type hash.
- */
- [[nodiscard]] constexpr id_type hash() const ENTT_NOEXCEPT {
- return identifier;
- }
- /**
- * @brief Type name.
- * @return Type name.
- */
- [[nodiscard]] constexpr std::string_view name() const ENTT_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]] inline constexpr bool operator==(const type_info &lhs, const type_info &rhs) ENTT_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]] inline constexpr bool operator!=(const type_info &lhs, const type_info &rhs) ENTT_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) ENTT_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) ENTT_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) ENTT_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) ENTT_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() ENTT_NOEXCEPT {
- if constexpr(std::is_same_v<Type, std::remove_cv_t<std::remove_reference_t<Type>>>) {
- static type_info instance{std::in_place_type<Type>};
- return instance;
- } else {
- return type_id<std::remove_cv_t<std::remove_reference_t<Type>>>();
- }
- }
- /*! @copydoc type_id */
- template<typename Type>
- [[nodiscard]] const type_info &type_id(Type &&) ENTT_NOEXCEPT {
- return type_id<std::remove_cv_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 <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.
- * @tparam The size of the type if `sizeof` accepts it, 0 otherwise.
- */
- 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))>>
- : 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 Type First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<std::size_t Index, typename Type, typename... Other>
- struct type_list_element<Index, type_list<Type, Other...>>
- : type_list_element<Index - 1u, type_list<Other...>> {};
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam Type First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<typename Type, typename... Other>
- struct type_list_element<0u, type_list<Type, Other...>> {
- /*! @brief Searched type. */
- using type = Type;
- };
- /**
- * @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 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;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename>
- struct type_list_unique;
- /**
- * @brief Removes duplicates types from a type list.
- * @tparam Type One of the types provided by the given type list.
- * @tparam Other The other types provided by the given type list.
- */
- template<typename Type, typename... Other>
- struct type_list_unique<type_list<Type, Other...>> {
- /*! @brief A type list without duplicate types. */
- using type = std::conditional_t<
- (std::is_same_v<Type, Other> || ...),
- typename type_list_unique<type_list<Other...>>::type,
- type_list_cat_t<type_list<Type>, typename type_list_unique<type_list<Other...>>::type>>;
- };
- /*! @brief Removes duplicates types from a type list. */
- template<>
- struct type_list_unique<type_list<>> {
- /*! @brief A type list without duplicate types. */
- using type = type_list<>;
- };
- /**
- * @brief Helper type.
- * @tparam Type A type list.
- */
- template<typename Type>
- using type_list_unique_t = typename type_list_unique<Type>::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::disjunction<std::is_same<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 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 value. */
- static constexpr auto value = Value;
- };
- /**
- * @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 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 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
- * Internal details not to be documented.
- */
- 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
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /*! @copydoc is_iterator */
- template<typename Type>
- struct is_iterator<Type, std::enable_if_t<!std::is_same_v<std::remove_const_t<std::remove_pointer_t<Type>>, void>>>
- : 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::conjunction<std::is_empty<Type>, std::negation<std::is_final<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;
- /**
- * @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, typename = void>
- struct is_equality_comparable: std::false_type {};
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- 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 Type, std::size_t... Index>
- [[nodiscard]] constexpr bool unpack_maybe_equality_comparable(std::index_sequence<Index...>) {
- return (is_equality_comparable<std::tuple_element_t<Index, Type>>::value && ...);
- }
- template<typename>
- [[nodiscard]] constexpr bool maybe_equality_comparable(choice_t<0>) {
- return true;
- }
- template<typename Type>
- [[nodiscard]] constexpr auto maybe_equality_comparable(choice_t<1>) -> decltype(std::declval<typename Type::value_type>(), bool{}) {
- if constexpr(is_iterator_v<Type>) {
- return true;
- } else if constexpr(std::is_same_v<typename Type::value_type, Type>) {
- return maybe_equality_comparable<Type>(choice<0>);
- } else {
- return is_equality_comparable<typename Type::value_type>::value;
- }
- }
- template<typename Type>
- [[nodiscard]] constexpr std::enable_if_t<is_complete_v<std::tuple_size<std::remove_const_t<Type>>>, bool> maybe_equality_comparable(choice_t<2>) {
- if constexpr(has_tuple_size_value<Type>::value) {
- return unpack_maybe_equality_comparable<Type>(std::make_index_sequence<std::tuple_size<Type>::value>{});
- } else {
- return maybe_equality_comparable<Type>(choice<1>);
- }
- }
- } // namespace internal
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /*! @copydoc is_equality_comparable */
- template<typename Type>
- struct is_equality_comparable<Type, std::void_t<decltype(std::declval<Type>() == std::declval<Type>())>>
- : std::bool_constant<internal::maybe_equality_comparable<Type>(choice<2>)> {};
- /**
- * @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 = std::add_const_t<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;
- } // namespace entt
- #endif
- namespace entt {
- /**
- * @brief A SBO friendly, type-safe container for single values of any type.
- * @tparam Len Size of the storage reserved for the small buffer optimization.
- * @tparam Align Optional alignment requirement.
- */
- template<std::size_t Len, std::size_t Align>
- class basic_any {
- enum class operation : std::uint8_t {
- copy,
- move,
- transfer,
- assign,
- destroy,
- compare,
- get
- };
- enum class policy : std::uint8_t {
- owner,
- ref,
- cref
- };
- using storage_type = std::aligned_storage_t<Len + !Len, Align>;
- using vtable_type = const void *(const operation, const basic_any &, const void *);
- template<typename Type>
- static constexpr bool in_situ = Len && alignof(Type) <= alignof(storage_type) && sizeof(Type) <= sizeof(storage_type) && std::is_nothrow_move_constructible_v<Type>;
- template<typename Type>
- static const void *basic_vtable([[maybe_unused]] const operation op, [[maybe_unused]] const basic_any &value, [[maybe_unused]] const void *other) {
- static_assert(!std::is_same_v<Type, void> && std::is_same_v<std::remove_cv_t<std::remove_reference_t<Type>>, Type>, "Invalid type");
- const Type *element = nullptr;
- if constexpr(in_situ<Type>) {
- element = value.owner() ? reinterpret_cast<const Type *>(&value.storage) : static_cast<const Type *>(value.instance);
- } else {
- element = static_cast<const Type *>(value.instance);
- }
- switch(op) {
- case operation::copy:
- if constexpr(std::is_copy_constructible_v<Type>) {
- static_cast<basic_any *>(const_cast<void *>(other))->initialize<Type>(*element);
- }
- break;
- case operation::move:
- if constexpr(in_situ<Type>) {
- if(value.owner()) {
- return new(&static_cast<basic_any *>(const_cast<void *>(other))->storage) Type{std::move(*const_cast<Type *>(element))};
- }
- }
- return (static_cast<basic_any *>(const_cast<void *>(other))->instance = std::exchange(const_cast<basic_any &>(value).instance, nullptr));
- case operation::transfer:
- if constexpr(std::is_move_assignable_v<Type>) {
- *const_cast<Type *>(element) = std::move(*static_cast<Type *>(const_cast<void *>(other)));
- return other;
- }
- [[fallthrough]];
- case operation::assign:
- if constexpr(std::is_copy_assignable_v<Type>) {
- *const_cast<Type *>(element) = *static_cast<const Type *>(other);
- return other;
- }
- break;
- case operation::destroy:
- if constexpr(in_situ<Type>) {
- element->~Type();
- } else if constexpr(std::is_array_v<Type>) {
- delete[] element;
- } else {
- delete element;
- }
- break;
- case operation::compare:
- if constexpr(!std::is_function_v<Type> && !std::is_array_v<Type> && is_equality_comparable_v<Type>) {
- return *static_cast<const Type *>(element) == *static_cast<const Type *>(other) ? other : nullptr;
- } else {
- return (element == other) ? other : nullptr;
- }
- case operation::get:
- return element;
- }
- return nullptr;
- }
- template<typename Type, typename... Args>
- void initialize([[maybe_unused]] Args &&...args) {
- if constexpr(!std::is_void_v<Type>) {
- info = &type_id<std::remove_cv_t<std::remove_reference_t<Type>>>();
- vtable = basic_vtable<std::remove_cv_t<std::remove_reference_t<Type>>>;
- if constexpr(std::is_lvalue_reference_v<Type>) {
- static_assert(sizeof...(Args) == 1u && (std::is_lvalue_reference_v<Args> && ...), "Invalid arguments");
- mode = std::is_const_v<std::remove_reference_t<Type>> ? policy::cref : policy::ref;
- instance = (std::addressof(args), ...);
- } else if constexpr(in_situ<Type>) {
- if constexpr(sizeof...(Args) != 0u && std::is_aggregate_v<Type>) {
- new(&storage) Type{std::forward<Args>(args)...};
- } else {
- new(&storage) Type(std::forward<Args>(args)...);
- }
- } else {
- if constexpr(sizeof...(Args) != 0u && std::is_aggregate_v<Type>) {
- instance = new Type{std::forward<Args>(args)...};
- } else {
- instance = new Type(std::forward<Args>(args)...);
- }
- }
- }
- }
- basic_any(const basic_any &other, const policy pol) ENTT_NOEXCEPT
- : instance{other.data()},
- info{other.info},
- vtable{other.vtable},
- mode{pol} {}
- public:
- /*! @brief Size of the internal storage. */
- static constexpr auto length = Len;
- /*! @brief Alignment requirement. */
- static constexpr auto alignment = Align;
- /*! @brief Default constructor. */
- constexpr basic_any() ENTT_NOEXCEPT
- : instance{},
- info{&type_id<void>()},
- vtable{},
- mode{policy::owner} {}
- /**
- * @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)
- : basic_any{} {
- initialize<Type>(std::forward<Args>(args)...);
- }
- /**
- * @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{} {
- initialize<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{} {
- if(other.vtable) {
- other.vtable(operation::copy, other, this);
- }
- }
- /**
- * @brief Move constructor.
- * @param other The instance to move from.
- */
- basic_any(basic_any &&other) ENTT_NOEXCEPT
- : instance{},
- info{other.info},
- vtable{other.vtable},
- mode{other.mode} {
- if(other.vtable) {
- other.vtable(operation::move, other, this);
- }
- }
- /*! @brief Frees the internal storage, whatever it means. */
- ~basic_any() {
- if(vtable && owner()) {
- vtable(operation::destroy, *this, nullptr);
- }
- }
- /**
- * @brief Copy assignment operator.
- * @param other The instance to copy from.
- * @return This any object.
- */
- basic_any &operator=(const basic_any &other) {
- reset();
- if(other.vtable) {
- other.vtable(operation::copy, other, this);
- }
- return *this;
- }
- /**
- * @brief Move assignment operator.
- * @param other The instance to move from.
- * @return This any object.
- */
- basic_any &operator=(basic_any &&other) ENTT_NOEXCEPT {
- reset();
- if(other.vtable) {
- other.vtable(operation::move, other, this);
- info = other.info;
- vtable = other.vtable;
- 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>
- 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 the object type if any, `type_id<void>()` otherwise.
- * @return The object type if any, `type_id<void>()` otherwise.
- */
- [[nodiscard]] const type_info &type() const ENTT_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 ENTT_NOEXCEPT {
- return vtable ? vtable(operation::get, *this, nullptr) : nullptr;
- }
- /**
- * @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 ENTT_NOEXCEPT {
- return *info == req ? data() : nullptr;
- }
- /**
- * @brief Returns an opaque pointer to the contained instance.
- * @return An opaque pointer the contained instance, if any.
- */
- [[nodiscard]] void *data() ENTT_NOEXCEPT {
- return (!vtable || mode == policy::cref) ? nullptr : const_cast<void *>(vtable(operation::get, *this, nullptr));
- }
- /**
- * @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) ENTT_NOEXCEPT {
- return *info == req ? data() : nullptr;
- }
- /**
- * @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) {
- reset();
- 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 any &other) {
- if(vtable && mode != policy::cref && *info == *other.info) {
- return (vtable(operation::assign, *this, other.data()) != nullptr);
- }
- return false;
- }
- /*! @copydoc assign */
- bool assign(any &&other) {
- if(vtable && mode != policy::cref && *info == *other.info) {
- if(auto *val = other.data(); val) {
- return (vtable(operation::transfer, *this, val) != nullptr);
- } else {
- return (vtable(operation::assign, *this, std::as_const(other).data()) != nullptr);
- }
- }
- return false;
- }
- /*! @brief Destroys contained object */
- void reset() {
- if(vtable && owner()) {
- vtable(operation::destroy, *this, nullptr);
- }
- info = &type_id<void>();
- vtable = nullptr;
- mode = policy::owner;
- }
- /**
- * @brief Returns false if a wrapper is empty, true otherwise.
- * @return False if the wrapper is empty, true otherwise.
- */
- [[nodiscard]] explicit operator bool() const ENTT_NOEXCEPT {
- return vtable != nullptr;
- }
- /**
- * @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.
- */
- bool operator==(const basic_any &other) const ENTT_NOEXCEPT {
- if(vtable && *info == *other.info) {
- return (vtable(operation::compare, *this, other.data()) != nullptr);
- }
- return (!vtable && !other.vtable);
- }
- /**
- * @brief Aliasing constructor.
- * @return A wrapper that shares a reference to an unmanaged object.
- */
- [[nodiscard]] basic_any as_ref() ENTT_NOEXCEPT {
- return basic_any{*this, (mode == policy::cref ? policy::cref : policy::ref)};
- }
- /*! @copydoc as_ref */
- [[nodiscard]] basic_any as_ref() const ENTT_NOEXCEPT {
- return basic_any{*this, policy::cref};
- }
- /**
- * @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 ENTT_NOEXCEPT {
- return (mode == policy::owner);
- }
- private:
- union {
- const void *instance;
- storage_type storage;
- };
- const type_info *info;
- vtable_type *vtable;
- policy mode;
- };
- /**
- * @brief Checks if two wrappers differ in their content.
- * @tparam Len Size of the storage reserved for the small buffer optimization.
- * @tparam Align Alignment requirement.
- * @param lhs A wrapper, either empty or not.
- * @param rhs A wrapper, either empty or not.
- * @return True if the two wrappers differ in their content, false otherwise.
- */
- template<std::size_t Len, std::size_t Align>
- [[nodiscard]] inline bool operator!=(const basic_any<Len, Align> &lhs, const basic_any<Len, Align> &rhs) ENTT_NOEXCEPT {
- return !(lhs == rhs);
- }
- /**
- * @brief Performs type-safe access to the contained object.
- * @tparam Type Type to which conversion is required.
- * @tparam Len Size of the storage 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>
- Type any_cast(const basic_any<Len, Align> &data) ENTT_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>
- Type any_cast(basic_any<Len, Align> &data) ENTT_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>
- Type any_cast(basic_any<Len, Align> &&data) ENTT_NOEXCEPT {
- if constexpr(std::is_copy_constructible_v<std::remove_cv_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));
- } else {
- 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>
- const Type *any_cast(const basic_any<Len, Align> *data) ENTT_NOEXCEPT {
- const auto &info = type_id<std::remove_cv_t<std::remove_reference_t<Type>>>();
- return static_cast<const Type *>(data->data(info));
- }
- /*! @copydoc any_cast */
- template<typename Type, std::size_t Len, std::size_t Align>
- Type *any_cast(basic_any<Len, Align> *data) ENTT_NOEXCEPT {
- const auto &info = type_id<std::remove_cv_t<std::remove_reference_t<Type>>>();
- // last attempt to make wrappers for const references return their values
- return static_cast<Type *>(static_cast<constness_as_t<basic_any<Len, Align>, Type> *>(data)->data(info));
- }
- /**
- * @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 storage 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>
- 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 storage 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>
- basic_any<Len, Align> forward_as_any(Type &&value) {
- return basic_any<Len, Align>{std::in_place_type<std::conditional_t<std::is_rvalue_reference_v<Type>, std::decay_t<Type>, Type>>, std::forward<Type>(value)};
- }
- } // namespace entt
- #endif
- // #include "../core/fwd.hpp"
- #ifndef ENTT_CORE_FWD_HPP
- #define ENTT_CORE_FWD_HPP
- #include <cstdint>
- #include <type_traits>
- // #include "../config/config.h"
- namespace entt {
- template<std::size_t Len = sizeof(double[2]), std::size_t = alignof(typename std::aligned_storage_t<Len + !Len>)>
- 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<>;
- } // namespace entt
- #endif
- // #include "../core/iterator.hpp"
- #ifndef ENTT_CORE_ITERATOR_HPP
- #define ENTT_CORE_ITERATOR_HPP
- #include <iterator>
- #include <memory>
- #include <utility>
- // #include "../config/config.h"
- 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 Pointer type. */
- using pointer = Type *;
- /*! @brief Default copy constructor, deleted on purpose. */
- input_iterator_pointer(const input_iterator_pointer &) = delete;
- /*! @brief Default move constructor. */
- input_iterator_pointer(input_iterator_pointer &&) = default;
- /**
- * @brief Constructs a proxy object by move.
- * @param val Value to use to initialize the proxy object.
- */
- input_iterator_pointer(Type &&val)
- : value{std::move(val)} {}
- /**
- * @brief Default copy assignment operator, deleted on purpose.
- * @return This proxy object.
- */
- input_iterator_pointer &operator=(const input_iterator_pointer &) = delete;
- /**
- * @brief Default move assignment operator.
- * @return This proxy object.
- */
- input_iterator_pointer &operator=(input_iterator_pointer &&) = default;
- /**
- * @brief Access operator for accessing wrapped values.
- * @return A pointer to the wrapped value.
- */
- [[nodiscard]] pointer operator->() ENTT_NOEXCEPT {
- return std::addressof(value);
- }
- private:
- Type value;
- };
- /**
- * @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. */
- iterable_adaptor() = default;
- /**
- * @brief Creates an iterable object from a pair of iterators.
- * @param from Begin iterator.
- * @param to End iterator.
- */
- iterable_adaptor(iterator from, sentinel to)
- : first{from},
- last{to} {}
- /**
- * @brief Returns an iterator to the beginning.
- * @return An iterator to the first element of the range.
- */
- [[nodiscard]] iterator begin() const ENTT_NOEXCEPT {
- return first;
- }
- /**
- * @brief Returns an iterator to the end.
- * @return An iterator to the element following the last element of the
- * range.
- */
- [[nodiscard]] sentinel end() const ENTT_NOEXCEPT {
- return last;
- }
- /*! @copydoc begin */
- [[nodiscard]] iterator cbegin() const ENTT_NOEXCEPT {
- return begin();
- }
- /*! @copydoc end */
- [[nodiscard]] sentinel cend() const ENTT_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 "../core/attribute.h"
- // #include "fwd.hpp"
- // #include "hashed_string.hpp"
- namespace entt {
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- namespace internal {
- struct ENTT_API type_index final {
- [[nodiscard]] static id_type next() ENTT_NOEXCEPT {
- static ENTT_MAYBE_ATOMIC(id_type) value{};
- return value++;
- }
- };
- template<typename Type>
- [[nodiscard]] constexpr auto stripped_type_name() ENTT_NOEXCEPT {
- #if defined ENTT_PRETTY_FUNCTION
- std::string_view pretty_function{ENTT_PRETTY_FUNCTION};
- auto first = pretty_function.find_first_not_of(' ', pretty_function.find_first_of(ENTT_PRETTY_FUNCTION_PREFIX) + 1);
- auto value = pretty_function.substr(first, pretty_function.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]] static constexpr std::string_view type_name(int) ENTT_NOEXCEPT {
- constexpr auto value = stripped_type_name<Type>();
- return value;
- }
- template<typename Type>
- [[nodiscard]] static std::string_view type_name(char) ENTT_NOEXCEPT {
- static const auto value = stripped_type_name<Type>();
- return value;
- }
- template<typename Type, auto = stripped_type_name<Type>().find_first_of('.')>
- [[nodiscard]] static constexpr id_type type_hash(int) ENTT_NOEXCEPT {
- constexpr auto stripped = stripped_type_name<Type>();
- constexpr auto value = hashed_string::value(stripped.data(), stripped.size());
- return value;
- }
- template<typename Type>
- [[nodiscard]] static id_type type_hash(char) ENTT_NOEXCEPT {
- static const auto value = [](const auto stripped) {
- return hashed_string::value(stripped.data(), stripped.size());
- }(stripped_type_name<Type>());
- return value;
- }
- } // namespace internal
- /**
- * Internal details not to be documented.
- * @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() ENTT_NOEXCEPT {
- static const id_type value = internal::type_index::next();
- return value;
- }
- /*! @copydoc value */
- [[nodiscard]] constexpr operator id_type() const ENTT_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() ENTT_NOEXCEPT {
- return internal::type_hash<Type>(0);
- #else
- [[nodiscard]] static constexpr id_type value() ENTT_NOEXCEPT {
- return type_index<Type>::value();
- #endif
- }
- /*! @copydoc value */
- [[nodiscard]] constexpr operator id_type() const ENTT_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() ENTT_NOEXCEPT {
- return internal::type_name<Type>(0);
- }
- /*! @copydoc value */
- [[nodiscard]] constexpr operator std::string_view() const ENTT_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>
- constexpr type_info(std::in_place_type_t<Type>) ENTT_NOEXCEPT
- : seq{type_index<std::remove_cv_t<std::remove_reference_t<Type>>>::value()},
- identifier{type_hash<std::remove_cv_t<std::remove_reference_t<Type>>>::value()},
- alias{type_name<std::remove_cv_t<std::remove_reference_t<Type>>>::value()} {}
- /**
- * @brief Type index.
- * @return Type index.
- */
- [[nodiscard]] constexpr id_type index() const ENTT_NOEXCEPT {
- return seq;
- }
- /**
- * @brief Type hash.
- * @return Type hash.
- */
- [[nodiscard]] constexpr id_type hash() const ENTT_NOEXCEPT {
- return identifier;
- }
- /**
- * @brief Type name.
- * @return Type name.
- */
- [[nodiscard]] constexpr std::string_view name() const ENTT_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]] inline constexpr bool operator==(const type_info &lhs, const type_info &rhs) ENTT_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]] inline constexpr bool operator!=(const type_info &lhs, const type_info &rhs) ENTT_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) ENTT_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) ENTT_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) ENTT_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) ENTT_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() ENTT_NOEXCEPT {
- if constexpr(std::is_same_v<Type, std::remove_cv_t<std::remove_reference_t<Type>>>) {
- static type_info instance{std::in_place_type<Type>};
- return instance;
- } else {
- return type_id<std::remove_cv_t<std::remove_reference_t<Type>>>();
- }
- }
- /*! @copydoc type_id */
- template<typename Type>
- [[nodiscard]] const type_info &type_id(Type &&) ENTT_NOEXCEPT {
- return type_id<std::remove_cv_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 <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.
- * @tparam The size of the type if `sizeof` accepts it, 0 otherwise.
- */
- 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))>>
- : 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 Type First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<std::size_t Index, typename Type, typename... Other>
- struct type_list_element<Index, type_list<Type, Other...>>
- : type_list_element<Index - 1u, type_list<Other...>> {};
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam Type First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<typename Type, typename... Other>
- struct type_list_element<0u, type_list<Type, Other...>> {
- /*! @brief Searched type. */
- using type = Type;
- };
- /**
- * @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 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;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename>
- struct type_list_unique;
- /**
- * @brief Removes duplicates types from a type list.
- * @tparam Type One of the types provided by the given type list.
- * @tparam Other The other types provided by the given type list.
- */
- template<typename Type, typename... Other>
- struct type_list_unique<type_list<Type, Other...>> {
- /*! @brief A type list without duplicate types. */
- using type = std::conditional_t<
- (std::is_same_v<Type, Other> || ...),
- typename type_list_unique<type_list<Other...>>::type,
- type_list_cat_t<type_list<Type>, typename type_list_unique<type_list<Other...>>::type>>;
- };
- /*! @brief Removes duplicates types from a type list. */
- template<>
- struct type_list_unique<type_list<>> {
- /*! @brief A type list without duplicate types. */
- using type = type_list<>;
- };
- /**
- * @brief Helper type.
- * @tparam Type A type list.
- */
- template<typename Type>
- using type_list_unique_t = typename type_list_unique<Type>::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::disjunction<std::is_same<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 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 value. */
- static constexpr auto value = Value;
- };
- /**
- * @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 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 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
- * Internal details not to be documented.
- */
- 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
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /*! @copydoc is_iterator */
- template<typename Type>
- struct is_iterator<Type, std::enable_if_t<!std::is_same_v<std::remove_const_t<std::remove_pointer_t<Type>>, void>>>
- : 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::conjunction<std::is_empty<Type>, std::negation<std::is_final<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;
- /**
- * @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, typename = void>
- struct is_equality_comparable: std::false_type {};
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- 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 Type, std::size_t... Index>
- [[nodiscard]] constexpr bool unpack_maybe_equality_comparable(std::index_sequence<Index...>) {
- return (is_equality_comparable<std::tuple_element_t<Index, Type>>::value && ...);
- }
- template<typename>
- [[nodiscard]] constexpr bool maybe_equality_comparable(choice_t<0>) {
- return true;
- }
- template<typename Type>
- [[nodiscard]] constexpr auto maybe_equality_comparable(choice_t<1>) -> decltype(std::declval<typename Type::value_type>(), bool{}) {
- if constexpr(is_iterator_v<Type>) {
- return true;
- } else if constexpr(std::is_same_v<typename Type::value_type, Type>) {
- return maybe_equality_comparable<Type>(choice<0>);
- } else {
- return is_equality_comparable<typename Type::value_type>::value;
- }
- }
- template<typename Type>
- [[nodiscard]] constexpr std::enable_if_t<is_complete_v<std::tuple_size<std::remove_const_t<Type>>>, bool> maybe_equality_comparable(choice_t<2>) {
- if constexpr(has_tuple_size_value<Type>::value) {
- return unpack_maybe_equality_comparable<Type>(std::make_index_sequence<std::tuple_size<Type>::value>{});
- } else {
- return maybe_equality_comparable<Type>(choice<1>);
- }
- }
- } // namespace internal
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /*! @copydoc is_equality_comparable */
- template<typename Type>
- struct is_equality_comparable<Type, std::void_t<decltype(std::declval<Type>() == std::declval<Type>())>>
- : std::bool_constant<internal::maybe_equality_comparable<Type>(choice<2>)> {};
- /**
- * @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 = std::add_const_t<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;
- } // namespace entt
- #endif
- // #include "../core/utility.hpp"
- #ifndef ENTT_CORE_UTILITY_HPP
- #define ENTT_CORE_UTILITY_HPP
- #include <utility>
- // #include "../config/config.h"
- 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<class Type>
- [[nodiscard]] constexpr Type &&operator()(Type &&value) const ENTT_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) ENTT_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) ENTT_NOEXCEPT {
- return func;
- }
- /**
- * @brief Helper type for visitors.
- * @tparam Func Types of function objects.
- */
- template<class... Func>
- struct overloaded: Func... {
- using Func::operator()...;
- };
- /**
- * @brief Deduction guide.
- * @tparam Func Types of function objects.
- */
- template<class... Func>
- overloaded(Func...) -> overloaded<Func...>;
- /**
- * @brief Basic implementation of a y-combinator.
- * @tparam Func Type of a potentially recursive function.
- */
- template<class Func>
- struct y_combinator {
- /**
- * @brief Constructs a y-combinator from a given function.
- * @param recursive A potentially recursive function.
- */
- y_combinator(Func recursive)
- : 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<class... Args>
- decltype(auto) operator()(Args &&...args) const {
- return func(*this, std::forward<Args>(args)...);
- }
- /*! @copydoc operator()() */
- template<class... Args>
- decltype(auto) operator()(Args &&...args) {
- return func(*this, std::forward<Args>(args)...);
- }
- private:
- Func func;
- };
- } // 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 "ctx.hpp"
- #ifndef ENTT_META_CTX_HPP
- #define ENTT_META_CTX_HPP
- // #include "../config/config.h"
- // #include "../core/attribute.h"
- #ifndef ENTT_CORE_ATTRIBUTE_H
- #define ENTT_CORE_ATTRIBUTE_H
- #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
- #endif
- namespace entt {
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- namespace internal {
- struct meta_type_node;
- struct ENTT_API meta_context {
- // we could use the lines below but VS2017 returns with an ICE if combined with ENTT_API despite the code being valid C++
- // inline static meta_type_node *local = nullptr;
- // inline static meta_type_node **global = &local;
- [[nodiscard]] static meta_type_node *&local() ENTT_NOEXCEPT {
- static meta_type_node *chain = nullptr;
- return chain;
- }
- [[nodiscard]] static meta_type_node **&global() ENTT_NOEXCEPT {
- static meta_type_node **chain = &local();
- return chain;
- }
- };
- } // namespace internal
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /*! @brief Opaque container for a meta context. */
- struct meta_ctx {
- /**
- * @brief Binds the meta system to a given context.
- * @param other A valid context to which to bind.
- */
- static void bind(meta_ctx other) ENTT_NOEXCEPT {
- internal::meta_context::global() = other.ctx;
- }
- private:
- internal::meta_type_node **ctx{&internal::meta_context::local()};
- };
- } // namespace entt
- #endif
- // #include "fwd.hpp"
- #ifndef ENTT_META_FWD_HPP
- #define ENTT_META_FWD_HPP
- namespace entt {
- class meta_sequence_container;
- class meta_associative_container;
- class meta_any;
- struct meta_handle;
- struct meta_prop;
- struct meta_data;
- struct meta_func;
- class meta_type;
- } // namespace entt
- #endif
- // #include "node.hpp"
- #ifndef ENTT_META_NODE_HPP
- #define ENTT_META_NODE_HPP
- #include <cstddef>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- // #include "../core/attribute.h"
- // #include "../core/enum.hpp"
- #ifndef ENTT_CORE_ENUM_HPP
- #define ENTT_CORE_ENUM_HPP
- #include <type_traits>
- // #include "../config/config.h"
- 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) ENTT_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) ENTT_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) ENTT_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) ENTT_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) ENTT_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) ENTT_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) ENTT_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) ENTT_NOEXCEPT {
- return (lhs = (lhs ^ rhs));
- }
- #endif
- // #include "../core/fwd.hpp"
- // #include "../core/type_info.hpp"
- // #include "../core/type_traits.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.
- * @tparam Type Potentially pointer-like type.
- */
- template<typename>
- 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;
- struct meta_handle;
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- namespace internal {
- enum class meta_traits : std::uint32_t {
- is_none = 0x0000,
- is_const = 0x0001,
- is_static = 0x0002,
- is_arithmetic = 0x0004,
- is_array = 0x0008,
- is_enum = 0x0010,
- is_class = 0x0020,
- is_pointer = 0x0040,
- is_meta_pointer_like = 0x0080,
- is_meta_sequence_container = 0x0100,
- is_meta_associative_container = 0x0200,
- _entt_enum_as_bitmask
- };
- struct meta_type_node;
- struct meta_prop_node {
- meta_prop_node *next;
- const meta_any &id;
- meta_any &value;
- };
- struct meta_base_node {
- meta_base_node *next;
- meta_type_node *const type;
- meta_any (*const cast)(meta_any) ENTT_NOEXCEPT;
- };
- struct meta_conv_node {
- meta_conv_node *next;
- meta_type_node *const type;
- meta_any (*const conv)(const meta_any &);
- };
- struct meta_ctor_node {
- using size_type = std::size_t;
- meta_ctor_node *next;
- const size_type arity;
- meta_type (*const arg)(const size_type) ENTT_NOEXCEPT;
- meta_any (*const invoke)(meta_any *const);
- };
- struct meta_data_node {
- using size_type = std::size_t;
- id_type id;
- const meta_traits traits;
- meta_data_node *next;
- meta_prop_node *prop;
- const size_type arity;
- meta_type_node *const type;
- meta_type (*const arg)(const size_type) ENTT_NOEXCEPT;
- bool (*const set)(meta_handle, meta_any);
- meta_any (*const get)(meta_handle);
- };
- struct meta_func_node {
- using size_type = std::size_t;
- id_type id;
- const meta_traits traits;
- meta_func_node *next;
- meta_prop_node *prop;
- const size_type arity;
- meta_type_node *const ret;
- meta_type (*const arg)(const size_type) ENTT_NOEXCEPT;
- meta_any (*const invoke)(meta_handle, meta_any *const);
- };
- struct meta_template_node {
- using size_type = std::size_t;
- const size_type arity;
- meta_type_node *const type;
- meta_type_node *(*const arg)(const size_type)ENTT_NOEXCEPT;
- };
- struct meta_type_node {
- using size_type = std::size_t;
- const type_info *info;
- id_type id;
- const meta_traits traits;
- meta_type_node *next;
- meta_prop_node *prop;
- const size_type size_of;
- meta_type_node *(*const remove_pointer)() ENTT_NOEXCEPT;
- meta_any (*const default_constructor)();
- double (*const conversion_helper)(void *, const void *);
- const meta_template_node *const templ;
- meta_ctor_node *ctor{nullptr};
- meta_base_node *base{nullptr};
- meta_conv_node *conv{nullptr};
- meta_data_node *data{nullptr};
- meta_func_node *func{nullptr};
- void (*dtor)(void *){nullptr};
- };
- template<typename... Args>
- meta_type_node *meta_arg_node(type_list<Args...>, const std::size_t index) ENTT_NOEXCEPT;
- template<typename Type>
- class ENTT_API meta_node {
- static_assert(std::is_same_v<Type, std::remove_cv_t<std::remove_reference_t<Type>>>, "Invalid type");
- [[nodiscard]] static auto *meta_default_constructor() ENTT_NOEXCEPT {
- if constexpr(std::is_default_constructible_v<Type>) {
- return +[]() { return meta_any{std::in_place_type<Type>}; };
- } else {
- return static_cast<std::decay_t<decltype(meta_type_node::default_constructor)>>(nullptr);
- }
- }
- [[nodiscard]] static auto *meta_conversion_helper() ENTT_NOEXCEPT {
- if constexpr(std::is_arithmetic_v<Type>) {
- return +[](void *bin, const void *value) {
- return bin ? static_cast<double>(*static_cast<Type *>(bin) = static_cast<Type>(*static_cast<const double *>(value))) : static_cast<double>(*static_cast<const Type *>(value));
- };
- } else if constexpr(std::is_enum_v<Type>) {
- return +[](void *bin, const void *value) {
- return bin ? static_cast<double>(*static_cast<Type *>(bin) = static_cast<Type>(static_cast<std::underlying_type_t<Type>>(*static_cast<const double *>(value)))) : static_cast<double>(*static_cast<const Type *>(value));
- };
- } else {
- return static_cast<std::decay_t<decltype(meta_type_node::conversion_helper)>>(nullptr);
- }
- }
- [[nodiscard]] static meta_template_node *meta_template_info() ENTT_NOEXCEPT {
- if constexpr(is_complete_v<meta_template_traits<Type>>) {
- static meta_template_node node{
- meta_template_traits<Type>::args_type::size,
- meta_node<typename meta_template_traits<Type>::class_type>::resolve(),
- [](const std::size_t index) ENTT_NOEXCEPT { return meta_arg_node(typename meta_template_traits<Type>::args_type{}, index); }
- // tricks clang-format
- };
- return &node;
- } else {
- return nullptr;
- }
- }
- public:
- [[nodiscard]] static meta_type_node *resolve() ENTT_NOEXCEPT {
- static meta_type_node node{
- &type_id<Type>(),
- {},
- internal::meta_traits::is_none
- | (std::is_arithmetic_v<Type> ? internal::meta_traits::is_arithmetic : internal::meta_traits::is_none)
- | (std::is_array_v<Type> ? internal::meta_traits::is_array : internal::meta_traits::is_none)
- | (std::is_enum_v<Type> ? internal::meta_traits::is_enum : internal::meta_traits::is_none)
- | (std::is_class_v<Type> ? internal::meta_traits::is_class : internal::meta_traits::is_none)
- | (std::is_pointer_v<Type> ? internal::meta_traits::is_pointer : internal::meta_traits::is_none)
- | (is_meta_pointer_like_v<Type> ? internal::meta_traits::is_meta_pointer_like : internal::meta_traits::is_none)
- | (is_complete_v<meta_sequence_container_traits<Type>> ? internal::meta_traits::is_meta_sequence_container : internal::meta_traits::is_none)
- | (is_complete_v<meta_associative_container_traits<Type>> ? internal::meta_traits::is_meta_associative_container : internal::meta_traits::is_none),
- nullptr,
- nullptr,
- size_of_v<Type>,
- &meta_node<std::remove_cv_t<std::remove_reference_t<std::remove_pointer_t<Type>>>>::resolve,
- meta_default_constructor(),
- meta_conversion_helper(),
- meta_template_info()
- // tricks clang-format
- };
- return &node;
- }
- };
- template<typename... Args>
- [[nodiscard]] meta_type_node *meta_arg_node(type_list<Args...>, const std::size_t index) ENTT_NOEXCEPT {
- meta_type_node *args[sizeof...(Args) + 1u]{nullptr, internal::meta_node<std::remove_cv_t<std::remove_reference_t<Args>>>::resolve()...};
- return args[index + 1u];
- }
- template<auto Member, typename Type>
- [[nodiscard]] static std::decay_t<decltype(std::declval<internal::meta_type_node>().*Member)> find_by(const Type &info_or_id, const internal::meta_type_node *node) ENTT_NOEXCEPT {
- for(auto *curr = node->*Member; curr; curr = curr->next) {
- if constexpr(std::is_same_v<Type, type_info>) {
- if(*curr->type->info == info_or_id) {
- return curr;
- }
- } else if constexpr(std::is_same_v<decltype(curr), meta_base_node *>) {
- if(curr->type->id == info_or_id) {
- return curr;
- }
- } else {
- if(curr->id == info_or_id) {
- return curr;
- }
- }
- }
- for(auto *curr = node->base; curr; curr = curr->next) {
- if(auto *ret = find_by<Member>(info_or_id, curr->type); ret) {
- return ret;
- }
- }
- return nullptr;
- }
- } // namespace internal
- /**
- * Internal details not to be documented.
- * @endcond
- */
- } // namespace entt
- #endif
- // #include "range.hpp"
- #ifndef ENTT_META_RANGE_HPP
- #define ENTT_META_RANGE_HPP
- #include <cstddef>
- #include <iterator>
- // #include "../core/iterator.hpp"
- namespace entt {
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- namespace internal {
- template<typename Type, typename Node>
- struct meta_range_iterator final {
- using difference_type = std::ptrdiff_t;
- using value_type = Type;
- using pointer = input_iterator_pointer<value_type>;
- using reference = value_type;
- using iterator_category = std::input_iterator_tag;
- using node_type = Node;
- meta_range_iterator() ENTT_NOEXCEPT
- : it{} {}
- meta_range_iterator(node_type *head) ENTT_NOEXCEPT
- : it{head} {}
- meta_range_iterator &operator++() ENTT_NOEXCEPT {
- return (it = it->next), *this;
- }
- meta_range_iterator operator++(int) ENTT_NOEXCEPT {
- meta_range_iterator orig = *this;
- return ++(*this), orig;
- }
- [[nodiscard]] reference operator*() const ENTT_NOEXCEPT {
- return it;
- }
- [[nodiscard]] pointer operator->() const ENTT_NOEXCEPT {
- return operator*();
- }
- [[nodiscard]] bool operator==(const meta_range_iterator &other) const ENTT_NOEXCEPT {
- return it == other.it;
- }
- [[nodiscard]] bool operator!=(const meta_range_iterator &other) const ENTT_NOEXCEPT {
- return !(*this == other);
- }
- private:
- node_type *it;
- };
- } // namespace internal
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /**
- * @brief Iterable range to use to iterate all types of meta objects.
- * @tparam Type Type of meta objects returned.
- * @tparam Node Type of meta nodes iterated.
- */
- template<typename Type, typename Node = typename Type::node_type>
- struct meta_range final {
- /*! @brief Node type. */
- using node_type = Node;
- /*! @brief Input iterator type. */
- using iterator = internal::meta_range_iterator<Type, Node>;
- /*! @brief Constant input iterator type. */
- using const_iterator = iterator;
- /*! @brief Default constructor. */
- meta_range() ENTT_NOEXCEPT = default;
- /**
- * @brief Constructs a meta range from a given node.
- * @param head The underlying node with which to construct the range.
- */
- meta_range(node_type *head) ENTT_NOEXCEPT
- : node{head} {}
- /**
- * @brief Returns an iterator to the beginning.
- * @return An iterator to the first meta object of the range.
- */
- [[nodiscard]] const_iterator cbegin() const ENTT_NOEXCEPT {
- return iterator{node};
- }
- /*! @copydoc cbegin */
- [[nodiscard]] iterator begin() const ENTT_NOEXCEPT {
- return cbegin();
- }
- /**
- * @brief Returns an iterator to the end.
- * @return An iterator to the element following the last meta object of the
- * range.
- */
- [[nodiscard]] const_iterator cend() const ENTT_NOEXCEPT {
- return iterator{};
- }
- /*! @copydoc cend */
- [[nodiscard]] iterator end() const ENTT_NOEXCEPT {
- return cend();
- }
- private:
- node_type *node{nullptr};
- };
- } // 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() ENTT_NOEXCEPT = default;
- /**
- * @brief Construct a proxy object for sequence containers.
- * @tparam Type Type of container to wrap.
- * @param instance The container to wrap.
- */
- template<typename Type>
- meta_sequence_container(std::in_place_type_t<Type>, any instance) ENTT_NOEXCEPT
- : value_type_node{internal::meta_node<std::remove_cv_t<std::remove_reference_t<typename Type::value_type>>>::resolve()},
- size_fn{&meta_sequence_container_traits<Type>::size},
- resize_fn{&meta_sequence_container_traits<Type>::resize},
- iter_fn{&meta_sequence_container_traits<Type>::iter},
- insert_fn{&meta_sequence_container_traits<Type>::insert},
- erase_fn{&meta_sequence_container_traits<Type>::erase},
- storage{std::move(instance)} {}
- [[nodiscard]] inline meta_type value_type() const ENTT_NOEXCEPT;
- [[nodiscard]] inline size_type size() const ENTT_NOEXCEPT;
- inline bool resize(const size_type);
- inline bool clear();
- [[nodiscard]] inline iterator begin();
- [[nodiscard]] inline iterator end();
- inline iterator insert(iterator, meta_any);
- inline iterator erase(iterator);
- [[nodiscard]] inline meta_any operator[](const size_type);
- [[nodiscard]] inline explicit operator bool() const ENTT_NOEXCEPT;
- private:
- internal::meta_type_node *value_type_node = nullptr;
- size_type (*size_fn)(const any &) ENTT_NOEXCEPT = nullptr;
- bool (*resize_fn)(any &, size_type) = nullptr;
- iterator (*iter_fn)(any &, const bool) = nullptr;
- iterator (*insert_fn)(any &, const std::ptrdiff_t, meta_any &) = nullptr;
- iterator (*erase_fn)(any &, const std::ptrdiff_t) = nullptr;
- any storage{};
- };
- /*! @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() ENTT_NOEXCEPT = default;
- /**
- * @brief Construct a proxy object for associative containers.
- * @tparam Type Type of container to wrap.
- * @param instance The container to wrap.
- */
- template<typename Type>
- meta_associative_container(std::in_place_type_t<Type>, any instance) ENTT_NOEXCEPT
- : key_only_container{meta_associative_container_traits<Type>::key_only},
- key_type_node{internal::meta_node<std::remove_cv_t<std::remove_reference_t<typename Type::key_type>>>::resolve()},
- mapped_type_node{nullptr},
- value_type_node{internal::meta_node<std::remove_cv_t<std::remove_reference_t<typename Type::value_type>>>::resolve()},
- size_fn{&meta_associative_container_traits<Type>::size},
- clear_fn{&meta_associative_container_traits<Type>::clear},
- iter_fn{&meta_associative_container_traits<Type>::iter},
- insert_fn{&meta_associative_container_traits<Type>::insert},
- erase_fn{&meta_associative_container_traits<Type>::erase},
- find_fn{&meta_associative_container_traits<Type>::find},
- storage{std::move(instance)} {
- if constexpr(!meta_associative_container_traits<Type>::key_only) {
- mapped_type_node = internal::meta_node<std::remove_cv_t<std::remove_reference_t<typename Type::mapped_type>>>::resolve();
- }
- }
- [[nodiscard]] inline bool key_only() const ENTT_NOEXCEPT;
- [[nodiscard]] inline meta_type key_type() const ENTT_NOEXCEPT;
- [[nodiscard]] inline meta_type mapped_type() const ENTT_NOEXCEPT;
- [[nodiscard]] inline meta_type value_type() const ENTT_NOEXCEPT;
- [[nodiscard]] inline size_type size() const ENTT_NOEXCEPT;
- inline bool clear();
- [[nodiscard]] inline iterator begin();
- [[nodiscard]] inline iterator end();
- inline bool insert(meta_any, meta_any);
- inline bool erase(meta_any);
- [[nodiscard]] inline iterator find(meta_any);
- [[nodiscard]] inline explicit operator bool() const ENTT_NOEXCEPT;
- private:
- bool key_only_container{};
- internal::meta_type_node *key_type_node = nullptr;
- internal::meta_type_node *mapped_type_node = nullptr;
- internal::meta_type_node *value_type_node = nullptr;
- size_type (*size_fn)(const any &) ENTT_NOEXCEPT = nullptr;
- bool (*clear_fn)(any &) = nullptr;
- iterator (*iter_fn)(any &, const bool) = nullptr;
- bool (*insert_fn)(any &, meta_any &, meta_any &) = nullptr;
- bool (*erase_fn)(any &, meta_any &) = nullptr;
- iterator (*find_fn)(any &, meta_any &) = nullptr;
- any storage{};
- };
- /*! @brief Opaque wrapper for values of any type. */
- class meta_any {
- enum class operation : std::uint8_t {
- deref,
- seq,
- assoc
- };
- using vtable_type = void(const operation, const any &, void *);
- template<typename Type>
- static void basic_vtable([[maybe_unused]] const operation op, [[maybe_unused]] const any &value, [[maybe_unused]] void *other) {
- static_assert(std::is_same_v<std::remove_cv_t<std::remove_reference_t<Type>>, Type>, "Invalid type");
- if constexpr(!std::is_void_v<Type>) {
- switch(op) {
- case operation::deref:
- if constexpr(is_meta_pointer_like_v<Type>) {
- if constexpr(std::is_function_v<std::remove_const_t<typename std::pointer_traits<Type>::element_type>>) {
- *static_cast<meta_any *>(other) = any_cast<Type>(value);
- } else if constexpr(!std::is_same_v<std::remove_const_t<typename std::pointer_traits<Type>::element_type>, void>) {
- using in_place_type = decltype(adl_meta_pointer_like<Type>::dereference(any_cast<const Type &>(value)));
- if constexpr(std::is_constructible_v<bool, Type>) {
- if(const auto &pointer_like = any_cast<const Type &>(value); pointer_like) {
- static_cast<meta_any *>(other)->emplace<in_place_type>(adl_meta_pointer_like<Type>::dereference(pointer_like));
- }
- } else {
- static_cast<meta_any *>(other)->emplace<in_place_type>(adl_meta_pointer_like<Type>::dereference(any_cast<const Type &>(value)));
- }
- }
- }
- break;
- case operation::seq:
- if constexpr(is_complete_v<meta_sequence_container_traits<Type>>) {
- *static_cast<meta_sequence_container *>(other) = {std::in_place_type<Type>, std::move(const_cast<any &>(value))};
- }
- break;
- case operation::assoc:
- if constexpr(is_complete_v<meta_associative_container_traits<Type>>) {
- *static_cast<meta_associative_container *>(other) = {std::in_place_type<Type>, std::move(const_cast<any &>(value))};
- }
- break;
- }
- }
- }
- void release() {
- if(node && node->dtor && storage.owner()) {
- node->dtor(storage.data());
- }
- }
- meta_any(const meta_any &other, any ref) ENTT_NOEXCEPT
- : storage{std::move(ref)},
- node{storage ? other.node : nullptr},
- vtable{storage ? other.vtable : &basic_vtable<void>} {}
- public:
- /*! @brief Default constructor. */
- meta_any() ENTT_NOEXCEPT
- : storage{},
- node{},
- vtable{&basic_vtable<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 meta_any(std::in_place_type_t<Type>, Args &&...args)
- : storage{std::in_place_type<Type>, std::forward<Args>(args)...},
- node{internal::meta_node<std::remove_cv_t<std::remove_reference_t<Type>>>::resolve()},
- vtable{&basic_vtable<std::remove_cv_t<std::remove_reference_t<Type>>>} {}
- /**
- * @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{std::in_place_type<std::remove_cv_t<std::remove_reference_t<Type>>>, std::forward<Type>(value)} {}
- /**
- * @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) ENTT_NOEXCEPT
- : storage{std::move(other.storage)},
- node{std::exchange(other.node, nullptr)},
- vtable{std::exchange(other.vtable, &basic_vtable<void>)} {}
- /*! @brief Frees the internal storage, whatever it means. */
- ~meta_any() {
- release();
- }
- /**
- * @brief Copy assignment operator.
- * @param other The instance to copy from.
- * @return This meta any object.
- */
- meta_any &operator=(const meta_any &other) {
- release();
- vtable = other.vtable;
- storage = other.storage;
- node = other.node;
- return *this;
- }
- /**
- * @brief Move assignment operator.
- * @param other The instance to move from.
- * @return This meta any object.
- */
- meta_any &operator=(meta_any &&other) ENTT_NOEXCEPT {
- release();
- vtable = std::exchange(other.vtable, &basic_vtable<void>);
- storage = std::move(other.storage);
- node = std::exchange(other.node, 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>
- 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::type */
- [[nodiscard]] inline meta_type type() const ENTT_NOEXCEPT;
- /*! @copydoc any::data */
- [[nodiscard]] const void *data() const ENTT_NOEXCEPT {
- return storage.data();
- }
- /*! @copydoc any::data */
- [[nodiscard]] void *data() ENTT_NOEXCEPT {
- return storage.data();
- }
- /**
- * @brief Invokes the underlying function, if possible.
- *
- * @sa meta_func::invoke
- *
- * @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(const id_type id, Args &&...args) const;
- /*! @copydoc invoke */
- template<typename... Args>
- meta_any invoke(const id_type id, Args &&...args);
- /**
- * @brief Sets the value of a given variable.
- *
- * The type of the value is such that a cast or conversion to the type of
- * the variable is possible. Otherwise, invoking the setter does nothing.
- *
- * @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(const 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(const id_type id) const;
- /*! @copydoc get */
- [[nodiscard]] meta_any get(const 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 {
- if(const auto &info = type_id<Type>(); node && *node->info == info) {
- return any_cast<Type>(&storage);
- } else if(node) {
- for(auto *it = node->base; it; it = it->next) {
- const auto as_const = it->cast(as_ref());
- if(const Type *base = as_const.template try_cast<Type>(); base) {
- return base;
- }
- }
- }
- return nullptr;
- }
- /*! @copydoc try_cast */
- template<typename Type>
- [[nodiscard]] Type *try_cast() {
- if(const auto &info = type_id<Type>(); node && *node->info == info) {
- return any_cast<Type>(&storage);
- } else if(node) {
- for(auto *it = node->base; it; it = it->next) {
- if(Type *base = it->cast(as_ref()).template try_cast<Type>(); base) {
- return base;
- }
- }
- }
- return nullptr;
- }
- /**
- * @brief Tries to cast an instance to a given type.
- *
- * The type of the instance must be such that the cast is possible.
- *
- * @warning
- * Attempting to perform an invalid cast results is undefined behavior.
- *
- * @tparam Type Type to which to cast the instance.
- * @return A reference to the contained instance.
- */
- template<typename Type>
- [[nodiscard]] 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]] 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 any object if there exists a viable conversion, 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 there exists a viable conversion, false otherwise.
- */
- [[nodiscard]] bool allow_cast(const meta_type &type) {
- if(auto other = std::as_const(*this).allow_cast(type); other) {
- if(other.storage.owner()) {
- std::swap(*this, other);
- }
- return true;
- }
- return false;
- }
- /**
- * @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 any object if there exists a viable conversion, an
- * invalid one otherwise.
- */
- template<typename Type>
- [[nodiscard]] meta_any allow_cast() const {
- const auto other = allow_cast(internal::meta_node<std::remove_cv_t<std::remove_reference_t<Type>>>::resolve());
- if constexpr(std::is_reference_v<Type> && !std::is_const_v<std::remove_reference_t<Type>>) {
- return other.storage.owner() ? other : meta_any{};
- } else {
- return other;
- }
- }
- /**
- * @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 there exists a viable conversion, false otherwise.
- */
- template<typename Type>
- bool allow_cast() {
- if(auto other = std::as_const(*this).allow_cast(internal::meta_node<std::remove_cv_t<std::remove_reference_t<Type>>>::resolve()); other) {
- if(other.storage.owner()) {
- std::swap(*this, other);
- return true;
- }
- return (static_cast<constness_as_t<any, std::remove_reference_t<const Type>> &>(storage).data() != nullptr);
- }
- return false;
- }
- /*! @copydoc any::emplace */
- template<typename Type, typename... Args>
- void emplace(Args &&...args) {
- release();
- vtable = &basic_vtable<std::remove_cv_t<std::remove_reference_t<Type>>>;
- storage.emplace<Type>(std::forward<Args>(args)...);
- node = internal::meta_node<std::remove_cv_t<std::remove_reference_t<Type>>>::resolve();
- }
- /*! @copydoc any::assign */
- bool assign(const meta_any &other);
- /*! @copydoc any::assign */
- bool assign(meta_any &&other);
- /*! @copydoc any::reset */
- void reset() {
- release();
- vtable = &basic_vtable<void>;
- storage.reset();
- node = nullptr;
- }
- /**
- * @brief Returns a sequence container proxy.
- * @return A sequence container proxy for the underlying object.
- */
- [[nodiscard]] meta_sequence_container as_sequence_container() ENTT_NOEXCEPT {
- any detached = storage.as_ref();
- meta_sequence_container proxy;
- vtable(operation::seq, detached, &proxy);
- return proxy;
- }
- /*! @copydoc as_sequence_container */
- [[nodiscard]] meta_sequence_container as_sequence_container() const ENTT_NOEXCEPT {
- any detached = storage.as_ref();
- meta_sequence_container proxy;
- vtable(operation::seq, detached, &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() ENTT_NOEXCEPT {
- any detached = storage.as_ref();
- meta_associative_container proxy;
- vtable(operation::assoc, detached, &proxy);
- return proxy;
- }
- /*! @copydoc as_associative_container */
- [[nodiscard]] meta_associative_container as_associative_container() const ENTT_NOEXCEPT {
- any detached = storage.as_ref();
- meta_associative_container proxy;
- vtable(operation::assoc, detached, &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 ENTT_NOEXCEPT {
- meta_any ret{};
- vtable(operation::deref, storage, &ret);
- return ret;
- }
- /**
- * @brief Returns false if a wrapper is invalid, true otherwise.
- * @return False if the wrapper is invalid, true otherwise.
- */
- [[nodiscard]] explicit operator bool() const ENTT_NOEXCEPT {
- return !(node == nullptr);
- }
- /*! @copydoc any::operator== */
- [[nodiscard]] bool operator==(const meta_any &other) const {
- return (!node && !other.node) || (node && other.node && *node->info == *other.node->info && storage == other.storage);
- }
- /*! @copydoc any::as_ref */
- [[nodiscard]] meta_any as_ref() ENTT_NOEXCEPT {
- return meta_any{*this, storage.as_ref()};
- }
- /*! @copydoc any::as_ref */
- [[nodiscard]] meta_any as_ref() const ENTT_NOEXCEPT {
- return meta_any{*this, storage.as_ref()};
- }
- /*! @copydoc any::owner */
- [[nodiscard]] bool owner() const ENTT_NOEXCEPT {
- return storage.owner();
- }
- private:
- any storage;
- internal::meta_type_node *node;
- vtable_type *vtable;
- };
- /**
- * @brief Checks if two wrappers differ in their content.
- * @param lhs A wrapper, either empty or not.
- * @param rhs A wrapper, either empty or not.
- * @return True if the two wrappers differ in their content, false otherwise.
- */
- [[nodiscard]] inline bool operator!=(const meta_any &lhs, const meta_any &rhs) ENTT_NOEXCEPT {
- return !(lhs == rhs);
- }
- /**
- * @brief Constructs a wrapper from a given type, passing it all arguments.
- * @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.
- * @return A properly initialized wrapper for an object of the given type.
- */
- template<typename Type, typename... Args>
- meta_any make_meta(Args &&...args) {
- return meta_any{std::in_place_type<Type>, std::forward<Args>(args)...};
- }
- /**
- * @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>
- meta_any forward_as_meta(Type &&value) {
- return meta_any{std::in_place_type<std::conditional_t<std::is_rvalue_reference_v<Type>, std::decay_t<Type>, Type>>, std::forward<Type>(value)};
- }
- /**
- * @brief Opaque pointers to instances of any type.
- *
- * A handle doesn't perform copies and isn't responsible for the contained
- * object. It doesn't prolong the lifetime of the pointed instance.<br/>
- * Handles are used to generate references to actual objects when needed.
- */
- struct meta_handle {
- /*! @brief Default constructor. */
- meta_handle() = default;
- /*! @brief Default copy constructor, deleted on purpose. */
- meta_handle(const meta_handle &) = delete;
- /*! @brief Default move constructor. */
- meta_handle(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 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) ENTT_NOEXCEPT
- : meta_handle{} {
- if constexpr(std::is_same_v<std::decay_t<Type>, meta_any>) {
- any = value.as_ref();
- } else {
- any.emplace<Type &>(value);
- }
- }
- /**
- * @brief Returns false if a handle is invalid, true otherwise.
- * @return False if the handle is invalid, true otherwise.
- */
- [[nodiscard]] explicit operator bool() const ENTT_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-> */
- [[nodiscard]] const meta_any *operator->() const {
- return &any;
- }
- private:
- meta_any any;
- };
- /*! @brief Opaque wrapper for properties of any type. */
- struct meta_prop {
- /*! @brief Node type. */
- using node_type = internal::meta_prop_node;
- /**
- * @brief Constructs an instance from a given node.
- * @param curr The underlying node with which to construct the instance.
- */
- meta_prop(const node_type *curr = nullptr) ENTT_NOEXCEPT
- : node{curr} {}
- /**
- * @brief Returns the stored key as a const reference.
- * @return A wrapper containing the key stored with the property.
- */
- [[nodiscard]] meta_any key() const {
- return node->id.as_ref();
- }
- /**
- * @brief Returns the stored value by copy.
- * @return A wrapper containing the value stored with the property.
- */
- [[nodiscard]] meta_any value() const {
- return node->value;
- }
- /**
- * @brief Returns true if an object is valid, false otherwise.
- * @return True if the object is valid, false otherwise.
- */
- [[nodiscard]] explicit operator bool() const ENTT_NOEXCEPT {
- return !(node == nullptr);
- }
- private:
- const node_type *node;
- };
- /*! @brief Opaque wrapper for data members. */
- struct meta_data {
- /*! @brief Node type. */
- using node_type = internal::meta_data_node;
- /*! @brief Unsigned integer type. */
- using size_type = typename node_type::size_type;
- /*! @copydoc meta_prop::meta_prop */
- meta_data(const node_type *curr = nullptr) ENTT_NOEXCEPT
- : node{curr} {}
- /*! @copydoc meta_type::id */
- [[nodiscard]] id_type id() const ENTT_NOEXCEPT {
- return node->id;
- }
- /**
- * @brief Returns the number of setters available.
- * @return The number of setters available.
- */
- [[nodiscard]] size_type arity() const ENTT_NOEXCEPT {
- return node->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 ENTT_NOEXCEPT {
- return !!(node->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 ENTT_NOEXCEPT {
- return !!(node->traits & internal::meta_traits::is_static);
- }
- /*! @copydoc meta_any::type */
- [[nodiscard]] inline meta_type type() const ENTT_NOEXCEPT;
- /**
- * @brief Sets the value of a given variable.
- *
- * It must be possible to cast the instance to the parent type of the data
- * member.<br/>
- * The type of the value is such that a cast or conversion to the type of
- * the variable is possible. Otherwise, invoking the setter does nothing.
- *
- * @tparam Type Type of value to assign.
- * @param instance An opaque instance of the underlying type.
- * @param value Parameter to use to set the underlying variable.
- * @return True in case of success, false otherwise.
- */
- template<typename Type>
- bool set(meta_handle instance, Type &&value) const {
- return node->set && node->set(std::move(instance), std::forward<Type>(value));
- }
- /**
- * @brief Gets the value of a given variable.
- *
- * It must be possible to cast the instance to the parent type of the data
- * member.
- *
- * @param instance An opaque instance of the underlying type.
- * @return A wrapper containing the value of the underlying variable.
- */
- [[nodiscard]] meta_any get(meta_handle instance) const {
- return node->get(std::move(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(const size_type index) const ENTT_NOEXCEPT;
- /**
- * @brief Returns a range to visit registered meta properties.
- * @return An iterable range to visit registered meta properties.
- */
- [[nodiscard]] meta_range<meta_prop> prop() const ENTT_NOEXCEPT {
- return node->prop;
- }
- /**
- * @brief Lookup function for registered meta properties.
- * @param key The key to use to search for a property.
- * @return The registered meta property for the given key, if any.
- */
- [[nodiscard]] meta_prop prop(meta_any key) const {
- for(auto curr: prop()) {
- if(curr.key() == key) {
- return curr;
- }
- }
- return nullptr;
- }
- /**
- * @brief Returns true if an object is valid, false otherwise.
- * @return True if the object is valid, false otherwise.
- */
- [[nodiscard]] explicit operator bool() const ENTT_NOEXCEPT {
- return !(node == nullptr);
- }
- private:
- const node_type *node;
- };
- /*! @brief Opaque wrapper for member functions. */
- struct meta_func {
- /*! @brief Node type. */
- using node_type = internal::meta_func_node;
- /*! @brief Unsigned integer type. */
- using size_type = typename node_type::size_type;
- /*! @copydoc meta_prop::meta_prop */
- meta_func(const node_type *curr = nullptr) ENTT_NOEXCEPT
- : node{curr} {}
- /*! @copydoc meta_type::id */
- [[nodiscard]] id_type id() const ENTT_NOEXCEPT {
- return node->id;
- }
- /**
- * @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 ENTT_NOEXCEPT {
- return node->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 ENTT_NOEXCEPT {
- return !!(node->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 ENTT_NOEXCEPT {
- return !!(node->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 ENTT_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(const size_type index) const ENTT_NOEXCEPT;
- /**
- * @brief Invokes the underlying function, if possible.
- *
- * To invoke a member function, the parameters must be such that a cast or
- * conversion to the required types is possible. Otherwise, an empty and
- * thus invalid wrapper is returned.<br/>
- * It must be possible to cast the instance to the parent type of the member
- * function.
- *
- * @param instance An opaque instance of 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.
- */
- meta_any invoke(meta_handle instance, meta_any *const args, const size_type sz) const {
- return sz == arity() ? node->invoke(std::move(instance), args) : meta_any{};
- }
- /**
- * @copybrief invoke
- *
- * @sa invoke
- *
- * @tparam Args Types of arguments to use to invoke the function.
- * @param instance An opaque instance of the underlying type.
- * @param args Parameters to use to invoke the function.
- * @return A wrapper containing the new instance, if any.
- */
- template<typename... Args>
- meta_any invoke(meta_handle instance, Args &&...args) const {
- meta_any arguments[sizeof...(Args) + 1u]{std::forward<Args>(args)...};
- return invoke(std::move(instance), arguments, sizeof...(Args));
- }
- /*! @copydoc meta_data::prop */
- [[nodiscard]] meta_range<meta_prop> prop() const ENTT_NOEXCEPT {
- return node->prop;
- }
- /**
- * @brief Lookup function for registered meta properties.
- * @param key The key to use to search for a property.
- * @return The registered meta property for the given key, if any.
- */
- [[nodiscard]] meta_prop prop(meta_any key) const {
- for(auto curr: prop()) {
- if(curr.key() == key) {
- return curr;
- }
- }
- return nullptr;
- }
- /**
- * @brief Returns true if an object is valid, false otherwise.
- * @return True if the object is valid, false otherwise.
- */
- [[nodiscard]] explicit operator bool() const ENTT_NOEXCEPT {
- return !(node == nullptr);
- }
- private:
- const node_type *node;
- };
- /*! @brief Opaque wrapper for types. */
- class meta_type {
- template<auto Member, typename Pred>
- [[nodiscard]] std::decay_t<decltype(std::declval<internal::meta_type_node>().*Member)> lookup(meta_any *const args, const typename internal::meta_type_node::size_type sz, Pred pred) const {
- std::decay_t<decltype(node->*Member)> candidate{};
- size_type extent{sz + 1u};
- bool ambiguous{};
- for(auto *curr = (node->*Member); curr; curr = curr->next) {
- if(pred(curr) && curr->arity == sz) {
- size_type direct{};
- size_type ext{};
- for(size_type next{}; next < sz && next == (direct + ext) && args[next]; ++next) {
- const auto type = args[next].type();
- const auto other = curr->arg(next);
- if(const auto &info = other.info(); info == type.info()) {
- ++direct;
- } else {
- ext += internal::find_by<&node_type::base>(info, type.node)
- || internal::find_by<&node_type::conv>(info, type.node)
- || (type.node->conversion_helper && other.node->conversion_helper);
- }
- }
- if((direct + ext) == sz) {
- if(ext < extent) {
- candidate = curr;
- extent = ext;
- ambiguous = false;
- } else if(ext == extent) {
- ambiguous = true;
- }
- }
- }
- }
- return (candidate && !ambiguous) ? candidate : decltype(candidate){};
- }
- public:
- /*! @brief Node type. */
- using node_type = internal::meta_type_node;
- /*! @brief Node type. */
- using base_node_type = internal::meta_base_node;
- /*! @brief Unsigned integer type. */
- using size_type = typename node_type::size_type;
- /*! @copydoc meta_prop::meta_prop */
- meta_type(const node_type *curr = nullptr) ENTT_NOEXCEPT
- : node{curr} {}
- /**
- * @brief Constructs an instance from a given base node.
- * @param curr The base node with which to construct the instance.
- */
- meta_type(const base_node_type *curr) ENTT_NOEXCEPT
- : node{curr ? curr->type : nullptr} {}
- /**
- * @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 ENTT_NOEXCEPT {
- return *node->info;
- }
- /**
- * @brief Returns the identifier assigned to a type.
- * @return The identifier assigned to the type.
- */
- [[nodiscard]] id_type id() const ENTT_NOEXCEPT {
- return node->id;
- }
- /**
- * @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 ENTT_NOEXCEPT {
- return 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 ENTT_NOEXCEPT {
- return !!(node->traits & internal::meta_traits::is_arithmetic);
- }
- /**
- * @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 ENTT_NOEXCEPT {
- return !!(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 ENTT_NOEXCEPT {
- return !!(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 ENTT_NOEXCEPT {
- return !!(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 ENTT_NOEXCEPT {
- return !!(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 ENTT_NOEXCEPT {
- return node->remove_pointer();
- }
- /**
- * @brief Checks whether a type is a pointer-like type or not.
- * @return True if the underlying type is a pointer-like one, false
- * otherwise.
- */
- [[nodiscard]] bool is_pointer_like() const ENTT_NOEXCEPT {
- return !!(node->traits & internal::meta_traits::is_meta_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 ENTT_NOEXCEPT {
- return !!(node->traits & internal::meta_traits::is_meta_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 ENTT_NOEXCEPT {
- return !!(node->traits & internal::meta_traits::is_meta_associative_container);
- }
- /**
- * @brief Checks whether a type refers to a recognized class template
- * specialization or not.
- * @return True if the type is a recognized class template specialization,
- * false otherwise.
- */
- [[nodiscard]] bool is_template_specialization() const ENTT_NOEXCEPT {
- return (node->templ != nullptr);
- }
- /**
- * @brief Returns the number of template arguments.
- * @return The number of template arguments.
- */
- [[nodiscard]] size_type template_arity() const ENTT_NOEXCEPT {
- return node->templ ? node->templ->arity : size_type{};
- }
- /**
- * @brief Returns a tag for the class template of the underlying type.
- *
- * @sa meta_class_template_tag
- *
- * @return The tag for the class template of the underlying type.
- */
- [[nodiscard]] inline meta_type template_type() const ENTT_NOEXCEPT {
- return node->templ ? node->templ->type : 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]] inline meta_type template_arg(const size_type index) const ENTT_NOEXCEPT {
- return index < template_arity() ? node->templ->arg(index) : meta_type{};
- }
- /**
- * @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, internal::meta_base_node> base() const ENTT_NOEXCEPT {
- return node->base;
- }
- /**
- * @brief Lookup function for registered base meta types.
- * @param id Unique identifier.
- * @return The registered base meta type for the given identifier, if any.
- */
- [[nodiscard]] meta_type base(const id_type id) const {
- return internal::find_by<&node_type::base>(id, node);
- }
- /**
- * @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> data() const ENTT_NOEXCEPT {
- return node->data;
- }
- /**
- * @brief Lookup function for registered meta data.
- *
- * Registered meta data of base classes will also be visited.
- *
- * @param id Unique identifier.
- * @return The registered meta data for the given identifier, if any.
- */
- [[nodiscard]] meta_data data(const id_type id) const {
- return internal::find_by<&node_type::data>(id, node);
- }
- /**
- * @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> func() const ENTT_NOEXCEPT {
- return node->func;
- }
- /**
- * @brief Lookup function for registered meta functions.
- *
- * Registered meta functions of base classes will also be visited.<br/>
- * In case of overloaded functions, the first one with the required
- * identifier will be returned.
- *
- * @param id Unique identifier.
- * @return The registered meta function for the given identifier, if any.
- */
- [[nodiscard]] meta_func func(const id_type id) const {
- return internal::find_by<&node_type::func>(id, node);
- }
- /**
- * @brief Creates an instance of the underlying type, if possible.
- *
- * Parameters are such that a cast or conversion to the required types is
- * possible. Otherwise, an empty and thus invalid wrapper is returned.<br/>
- * If suitable, the implicitly generated default constructor is used.
- *
- * @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 {
- const auto *candidate = lookup<&node_type::ctor>(args, sz, [](const auto *) { return true; });
- return candidate ? candidate->invoke(args) : ((!sz && node->default_constructor) ? node->default_constructor() : meta_any{});
- }
- /**
- * @copybrief construct
- *
- * @sa 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 {
- meta_any arguments[sizeof...(Args) + 1u]{std::forward<Args>(args)...};
- return construct(arguments, sizeof...(Args));
- }
- /**
- * @brief Invokes a function given an identifier, if possible.
- *
- * It must be possible to cast the instance to the parent type of the member
- * function.
- *
- * @sa meta_func::invoke
- *
- * @param id Unique identifier.
- * @param instance An opaque instance of 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.
- */
- meta_any invoke(const id_type id, meta_handle instance, meta_any *const args, const size_type sz) const {
- const auto *candidate = lookup<&node_type::func>(args, sz, [id](const auto *curr) { return curr->id == id; });
- for(auto it = base().begin(), last = base().end(); it != last && !candidate; ++it) {
- candidate = it->lookup<&node_type::func>(args, sz, [id](const auto *curr) { return curr->id == id; });
- }
- return candidate ? candidate->invoke(std::move(instance), args) : meta_any{};
- }
- /**
- * @copybrief invoke
- *
- * @sa invoke
- *
- * @param id Unique identifier.
- * @tparam Args Types of arguments to use to invoke the function.
- * @param instance An opaque instance of the underlying type.
- * @param args Parameters to use to invoke the function.
- * @return A wrapper containing the new instance, if any.
- */
- template<typename... Args>
- meta_any invoke(const id_type id, meta_handle instance, Args &&...args) const {
- meta_any arguments[sizeof...(Args) + 1u]{std::forward<Args>(args)...};
- return invoke(id, std::move(instance), arguments, sizeof...(Args));
- }
- /**
- * @brief Sets the value of a given variable.
- *
- * It must be possible to cast the instance to the parent type of the data
- * member.<br/>
- * The type of the value is such that a cast or conversion to the type of
- * the variable is possible. Otherwise, invoking the setter does nothing.
- *
- * @tparam Type Type of value to assign.
- * @param id Unique identifier.
- * @param instance An opaque instance of the underlying type.
- * @param value Parameter to use to set the underlying variable.
- * @return True in case of success, false otherwise.
- */
- template<typename Type>
- bool set(const id_type id, meta_handle instance, Type &&value) const {
- const auto candidate = data(id);
- return candidate && candidate.set(std::move(instance), std::forward<Type>(value));
- }
- /**
- * @brief Gets the value of a given variable.
- *
- * It must be possible to cast the instance to the parent type of the data
- * member.
- *
- * @param id Unique identifier.
- * @param instance An opaque instance of the underlying type.
- * @return A wrapper containing the value of the underlying variable.
- */
- [[nodiscard]] meta_any get(const id_type id, meta_handle instance) const {
- const auto candidate = data(id);
- return candidate ? candidate.get(std::move(instance)) : meta_any{};
- }
- /**
- * @brief Returns a range to visit registered top-level meta properties.
- * @return An iterable range to visit registered top-level meta properties.
- */
- [[nodiscard]] meta_range<meta_prop> prop() const ENTT_NOEXCEPT {
- return node->prop;
- }
- /**
- * @brief Lookup function for meta properties.
- *
- * Properties of base classes are also visited.
- *
- * @param key The key to use to search for a property.
- * @return The registered meta property for the given key, if any.
- */
- [[nodiscard]] meta_prop prop(meta_any key) const {
- return internal::find_by<&internal::meta_type_node::prop>(key, node);
- }
- /**
- * @brief Returns true if an object is valid, false otherwise.
- * @return True if the object is valid, false otherwise.
- */
- [[nodiscard]] explicit operator bool() const ENTT_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_type &other) const ENTT_NOEXCEPT {
- return (!node && !other.node) || (node && other.node && *node->info == *other.node->info);
- }
- private:
- const node_type *node;
- };
- /**
- * @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_type &lhs, const meta_type &rhs) ENTT_NOEXCEPT {
- return !(lhs == rhs);
- }
- [[nodiscard]] inline meta_type meta_any::type() const ENTT_NOEXCEPT {
- return node;
- }
- template<typename... Args>
- 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(const auto &info = type.info(); node && *node->info == info) {
- return as_ref();
- } else if(node) {
- for(auto *it = node->conv; it; it = it->next) {
- if(*it->type->info == info) {
- return it->conv(*this);
- }
- }
- if(node->conversion_helper && (type.is_arithmetic() || type.is_enum())) {
- // exploits the fact that arithmetic types and enums are also default constructible
- auto other = type.construct();
- ENTT_ASSERT(other.node->conversion_helper, "Conversion helper not found");
- const auto value = node->conversion_helper(nullptr, storage.data());
- other.node->conversion_helper(other.storage.data(), &value);
- return other;
- }
- for(auto *it = node->base; it; it = it->next) {
- const auto as_const = it->cast(as_ref());
- if(auto other = as_const.allow_cast(type); other) {
- return other;
- }
- }
- }
- return {};
- }
- inline bool meta_any::assign(const meta_any &other) {
- auto value = other.allow_cast(node);
- return value && storage.assign(std::move(value.storage));
- }
- inline bool meta_any::assign(meta_any &&other) {
- if(*node->info == *other.node->info) {
- return storage.assign(std::move(other.storage));
- }
- return assign(std::as_const(other));
- }
- [[nodiscard]] inline meta_type meta_data::type() const ENTT_NOEXCEPT {
- return node->type;
- }
- [[nodiscard]] inline meta_type meta_func::ret() const ENTT_NOEXCEPT {
- return node->ret;
- }
- [[nodiscard]] inline meta_type meta_data::arg(const size_type index) const ENTT_NOEXCEPT {
- return index < arity() ? node->arg(index) : meta_type{};
- }
- [[nodiscard]] inline meta_type meta_func::arg(const size_type index) const ENTT_NOEXCEPT {
- return index < arity() ? node->arg(index) : meta_type{};
- }
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- class meta_sequence_container::meta_iterator final {
- friend class meta_sequence_container;
- using deref_fn_type = meta_any(const any &, const std::ptrdiff_t);
- template<typename It>
- static meta_any deref_fn(const any &value, const std::ptrdiff_t pos) {
- return meta_any{std::in_place_type<typename std::iterator_traits<It>::reference>, any_cast<const It &>(value)[pos]};
- }
- public:
- using difference_type = std::ptrdiff_t;
- using value_type = meta_any;
- using pointer = input_iterator_pointer<value_type>;
- using reference = value_type;
- using iterator_category = std::input_iterator_tag;
- meta_iterator() ENTT_NOEXCEPT
- : deref{},
- offset{},
- handle{} {}
- template<typename Type>
- explicit meta_iterator(Type &cont, const difference_type init) ENTT_NOEXCEPT
- : deref{&deref_fn<decltype(cont.begin())>},
- offset{init},
- handle{cont.begin()} {}
- meta_iterator &operator++() ENTT_NOEXCEPT {
- return ++offset, *this;
- }
- meta_iterator operator++(int value) ENTT_NOEXCEPT {
- meta_iterator orig = *this;
- offset += ++value;
- return orig;
- }
- meta_iterator &operator--() ENTT_NOEXCEPT {
- return --offset, *this;
- }
- meta_iterator operator--(int value) ENTT_NOEXCEPT {
- meta_iterator orig = *this;
- offset -= ++value;
- return orig;
- }
- [[nodiscard]] reference operator*() const {
- return deref(handle, offset);
- }
- [[nodiscard]] pointer operator->() const {
- return operator*();
- }
- [[nodiscard]] explicit operator bool() const ENTT_NOEXCEPT {
- return static_cast<bool>(handle);
- }
- [[nodiscard]] bool operator==(const meta_iterator &other) const ENTT_NOEXCEPT {
- return offset == other.offset;
- }
- [[nodiscard]] bool operator!=(const meta_iterator &other) const ENTT_NOEXCEPT {
- return !(*this == other);
- }
- private:
- deref_fn_type *deref;
- difference_type offset;
- any handle;
- };
- class meta_associative_container::meta_iterator final {
- enum class operation : std::uint8_t {
- incr,
- deref
- };
- using vtable_type = void(const operation, const any &, std::pair<meta_any, meta_any> *);
- template<bool KeyOnly, typename It>
- static void basic_vtable(const operation op, const any &value, std::pair<meta_any, meta_any> *other) {
- switch(op) {
- case operation::incr:
- ++any_cast<It &>(const_cast<any &>(value));
- break;
- case operation::deref:
- const auto &it = any_cast<const It &>(value);
- 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);
- }
- break;
- }
- }
- public:
- using difference_type = std::ptrdiff_t;
- using value_type = std::pair<meta_any, meta_any>;
- using pointer = input_iterator_pointer<value_type>;
- using reference = value_type;
- using iterator_category = std::input_iterator_tag;
- meta_iterator() ENTT_NOEXCEPT
- : vtable{},
- handle{} {}
- template<bool KeyOnly, typename It>
- meta_iterator(std::integral_constant<bool, KeyOnly>, It iter) ENTT_NOEXCEPT
- : vtable{&basic_vtable<KeyOnly, It>},
- handle{std::move(iter)} {}
- meta_iterator &operator++() ENTT_NOEXCEPT {
- vtable(operation::incr, handle, nullptr);
- return *this;
- }
- meta_iterator operator++(int) ENTT_NOEXCEPT {
- meta_iterator orig = *this;
- return ++(*this), orig;
- }
- [[nodiscard]] reference operator*() const {
- reference other;
- vtable(operation::deref, handle, &other);
- return other;
- }
- [[nodiscard]] pointer operator->() const {
- return operator*();
- }
- [[nodiscard]] explicit operator bool() const ENTT_NOEXCEPT {
- return static_cast<bool>(handle);
- }
- [[nodiscard]] bool operator==(const meta_iterator &other) const ENTT_NOEXCEPT {
- return handle == other.handle;
- }
- [[nodiscard]] bool operator!=(const meta_iterator &other) const ENTT_NOEXCEPT {
- return !(*this == other);
- }
- private:
- vtable_type *vtable;
- any handle;
- };
- /**
- * Internal details not to be documented.
- * @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 ENTT_NOEXCEPT {
- return value_type_node;
- }
- /**
- * @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 ENTT_NOEXCEPT {
- return size_fn(storage);
- }
- /**
- * @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 resize_fn(storage, sz);
- }
- /**
- * @brief Clears the content of a container.
- * @return True in case of success, false otherwise.
- */
- inline bool meta_sequence_container::clear() {
- return resize_fn(storage, 0u);
- }
- /**
- * @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 iter_fn(storage, 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 iter_fn(storage, 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(iterator it, meta_any value) {
- return insert_fn(storage, it.offset, value);
- }
- /**
- * @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(iterator it) {
- return erase_fn(storage, it.offset);
- }
- /**
- * @brief Returns a reference to the element at a given location of a container
- * (no bounds checking is performed).
- * @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 ENTT_NOEXCEPT {
- return static_cast<bool>(storage);
- }
- /**
- * @brief Returns true if a container is also key-only, false otherwise.
- * @return True if the associative container is also key-only, false otherwise.
- */
- [[nodiscard]] inline bool meta_associative_container::key_only() const ENTT_NOEXCEPT {
- return key_only_container;
- }
- /**
- * @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 ENTT_NOEXCEPT {
- return key_type_node;
- }
- /**
- * @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 ENTT_NOEXCEPT {
- return mapped_type_node;
- }
- /*! @copydoc meta_sequence_container::value_type */
- [[nodiscard]] inline meta_type meta_associative_container::value_type() const ENTT_NOEXCEPT {
- return value_type_node;
- }
- /*! @copydoc meta_sequence_container::size */
- [[nodiscard]] inline meta_associative_container::size_type meta_associative_container::size() const ENTT_NOEXCEPT {
- return size_fn(storage);
- }
- /*! @copydoc meta_sequence_container::clear */
- inline bool meta_associative_container::clear() {
- return clear_fn(storage);
- }
- /*! @copydoc meta_sequence_container::begin */
- [[nodiscard]] inline meta_associative_container::iterator meta_associative_container::begin() {
- return iter_fn(storage, false);
- }
- /*! @copydoc meta_sequence_container::end */
- [[nodiscard]] inline meta_associative_container::iterator meta_associative_container::end() {
- return iter_fn(storage, true);
- }
- /**
- * @brief Inserts an element (a key/value pair) into a container.
- * @param key The key of the element to insert.
- * @param value The value of the element to insert.
- * @return A bool denoting whether the insertion took place.
- */
- inline bool meta_associative_container::insert(meta_any key, meta_any value = {}) {
- return insert_fn(storage, key, value);
- }
- /**
- * @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 bool meta_associative_container::erase(meta_any key) {
- return erase_fn(storage, key);
- }
- /**
- * @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 find_fn(storage, key);
- }
- /**
- * @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 ENTT_NOEXCEPT {
- return static_cast<bool>(storage);
- }
- } // namespace entt
- #endif
- // #include "type_traits.hpp"
- namespace entt {
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- namespace internal {
- template<typename, typename = void>
- struct is_dynamic_sequence_container: std::false_type {};
- template<typename Type>
- struct is_dynamic_sequence_container<Type, std::void_t<decltype(&Type::reserve)>>: std::true_type {};
- template<typename, typename = void>
- struct is_key_only_meta_associative_container: std::true_type {};
- template<typename Type>
- struct is_key_only_meta_associative_container<Type, std::void_t<typename Type::mapped_type>>: std::false_type {};
- template<typename Type>
- struct basic_meta_sequence_container_traits {
- using iterator = meta_sequence_container::iterator;
- using size_type = std::size_t;
- [[nodiscard]] static size_type size(const any &container) ENTT_NOEXCEPT {
- return any_cast<const Type &>(container).size();
- }
- [[nodiscard]] static bool resize([[maybe_unused]] any &container, [[maybe_unused]] size_type sz) {
- if constexpr(is_dynamic_sequence_container<Type>::value) {
- if(auto *const cont = any_cast<Type>(&container); cont) {
- cont->resize(sz);
- return true;
- }
- }
- return false;
- }
- [[nodiscard]] static iterator iter(any &container, const bool as_end) {
- if(auto *const cont = any_cast<Type>(&container); cont) {
- return iterator{*cont, static_cast<typename iterator::difference_type>(as_end * cont->size())};
- }
- const Type &as_const = any_cast<const Type &>(container);
- return iterator{as_const, static_cast<typename iterator::difference_type>(as_end * as_const.size())};
- }
- [[nodiscard]] static iterator insert([[maybe_unused]] any &container, [[maybe_unused]] const std::ptrdiff_t offset, [[maybe_unused]] meta_any &value) {
- if constexpr(is_dynamic_sequence_container<Type>::value) {
- if(auto *const cont = any_cast<Type>(&container); cont) {
- // this abomination is necessary because only on macos value_type and const_reference are different types for std::vector<bool>
- if(value.allow_cast<typename Type::const_reference>() || value.allow_cast<typename Type::value_type>()) {
- const auto *element = value.try_cast<std::remove_reference_t<typename Type::const_reference>>();
- const auto curr = cont->insert(cont->begin() + offset, element ? *element : value.cast<typename Type::value_type>());
- return iterator{*cont, curr - cont->begin()};
- }
- }
- }
- return {};
- }
- [[nodiscard]] static iterator erase([[maybe_unused]] any &container, [[maybe_unused]] const std::ptrdiff_t offset) {
- if constexpr(is_dynamic_sequence_container<Type>::value) {
- if(auto *const cont = any_cast<Type>(&container); cont) {
- const auto curr = cont->erase(cont->begin() + offset);
- return iterator{*cont, curr - cont->begin()};
- }
- }
- return {};
- }
- };
- template<typename Type>
- struct basic_meta_associative_container_traits {
- using iterator = meta_associative_container::iterator;
- using size_type = std::size_t;
- static constexpr auto key_only = is_key_only_meta_associative_container<Type>::value;
- [[nodiscard]] static size_type size(const any &container) ENTT_NOEXCEPT {
- return any_cast<const Type &>(container).size();
- }
- [[nodiscard]] static bool clear(any &container) {
- if(auto *const cont = any_cast<Type>(&container); cont) {
- cont->clear();
- return true;
- }
- return false;
- }
- [[nodiscard]] static iterator iter(any &container, const bool as_end) {
- if(auto *const cont = any_cast<Type>(&container); cont) {
- return iterator{std::integral_constant<bool, key_only>{}, as_end ? cont->end() : cont->begin()};
- }
- const auto &as_const = any_cast<const Type &>(container);
- return iterator{std::integral_constant<bool, key_only>{}, as_end ? as_const.end() : as_const.begin()};
- }
- [[nodiscard]] static bool insert(any &container, meta_any &key, [[maybe_unused]] meta_any &value) {
- auto *const cont = any_cast<Type>(&container);
- if constexpr(is_key_only_meta_associative_container<Type>::value) {
- return cont && key.allow_cast<const typename Type::key_type &>()
- && cont->insert(key.cast<const typename Type::key_type &>()).second;
- } else {
- return cont && key.allow_cast<const typename Type::key_type &>() && value.allow_cast<const typename Type::mapped_type &>()
- && cont->emplace(key.cast<const typename Type::key_type &>(), value.cast<const typename Type::mapped_type &>()).second;
- }
- }
- [[nodiscard]] static bool erase(any &container, meta_any &key) {
- auto *const cont = any_cast<Type>(&container);
- return cont && key.allow_cast<const typename Type::key_type &>()
- && (cont->erase(key.cast<const typename Type::key_type &>()) != cont->size());
- }
- [[nodiscard]] static iterator find(any &container, meta_any &key) {
- if(key.allow_cast<const typename Type::key_type &>()) {
- if(auto *const cont = any_cast<Type>(&container); cont) {
- return iterator{std::integral_constant<bool, key_only>{}, cont->find(key.cast<const typename Type::key_type &>())};
- }
- return iterator{std::integral_constant<bool, key_only>{}, any_cast<const Type &>(container).find(key.cast<const typename Type::key_type &>())};
- }
- return {};
- }
- };
- } // namespace internal
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /**
- * @brief Meta sequence container traits for `std::vector`s of any type.
- * @tparam Type The type of elements.
- * @tparam Args Other arguments.
- */
- template<typename Type, typename... Args>
- struct meta_sequence_container_traits<std::vector<Type, Args...>>
- : internal::basic_meta_sequence_container_traits<std::vector<Type, Args...>> {};
- /**
- * @brief Meta sequence container traits for `std::array`s of any type.
- * @tparam Type The type of elements.
- * @tparam N The number of elements.
- */
- template<typename Type, auto N>
- struct meta_sequence_container_traits<std::array<Type, N>>
- : internal::basic_meta_sequence_container_traits<std::array<Type, N>> {};
- /**
- * @brief Meta associative container traits for `std::map`s of any type.
- * @tparam Key The key type of elements.
- * @tparam Value The value type of elements.
- * @tparam Args Other arguments.
- */
- template<typename Key, typename Value, typename... Args>
- struct meta_associative_container_traits<std::map<Key, Value, Args...>>
- : internal::basic_meta_associative_container_traits<std::map<Key, Value, Args...>> {};
- /**
- * @brief Meta associative container traits for `std::unordered_map`s of any
- * type.
- * @tparam Key The key type of elements.
- * @tparam Value The value type of elements.
- * @tparam Args Other arguments.
- */
- template<typename Key, typename Value, typename... Args>
- struct meta_associative_container_traits<std::unordered_map<Key, Value, Args...>>
- : internal::basic_meta_associative_container_traits<std::unordered_map<Key, Value, Args...>> {};
- /**
- * @brief Meta associative container traits for `std::set`s of any type.
- * @tparam Key The type of elements.
- * @tparam Args Other arguments.
- */
- template<typename Key, typename... Args>
- struct meta_associative_container_traits<std::set<Key, Args...>>
- : internal::basic_meta_associative_container_traits<std::set<Key, Args...>> {};
- /**
- * @brief Meta associative container traits for `std::unordered_set`s of any
- * type.
- * @tparam Key The type of elements.
- * @tparam Args Other arguments.
- */
- template<typename Key, typename... Args>
- struct meta_associative_container_traits<std::unordered_set<Key, Args...>>
- : internal::basic_meta_associative_container_traits<std::unordered_set<Key, Args...>> {};
- /**
- * @brief Meta associative container traits for `dense_map`s of any type.
- * @tparam Key The key type of the elements.
- * @tparam Type The value type of the elements.
- * @tparam Args Other arguments.
- */
- template<typename Key, typename Type, typename... Args>
- struct meta_associative_container_traits<dense_map<Key, Type, Args...>>
- : internal::basic_meta_associative_container_traits<dense_map<Key, Type, Args...>> {};
- /**
- * @brief Meta associative container traits for `dense_set`s of any type.
- * @tparam Type The value type of the elements.
- * @tparam Args Other arguments.
- */
- template<typename Type, typename... Args>
- struct meta_associative_container_traits<dense_set<Type, Args...>>
- : internal::basic_meta_associative_container_traits<dense_set<Type, Args...>> {};
- } // namespace entt
- #endif
- // #include "meta/ctx.hpp"
- #ifndef ENTT_META_CTX_HPP
- #define ENTT_META_CTX_HPP
- // #include "../config/config.h"
- // #include "../core/attribute.h"
- namespace entt {
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- namespace internal {
- struct meta_type_node;
- struct ENTT_API meta_context {
- // we could use the lines below but VS2017 returns with an ICE if combined with ENTT_API despite the code being valid C++
- // inline static meta_type_node *local = nullptr;
- // inline static meta_type_node **global = &local;
- [[nodiscard]] static meta_type_node *&local() ENTT_NOEXCEPT {
- static meta_type_node *chain = nullptr;
- return chain;
- }
- [[nodiscard]] static meta_type_node **&global() ENTT_NOEXCEPT {
- static meta_type_node **chain = &local();
- return chain;
- }
- };
- } // namespace internal
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /*! @brief Opaque container for a meta context. */
- struct meta_ctx {
- /**
- * @brief Binds the meta system to a given context.
- * @param other A valid context to which to bind.
- */
- static void bind(meta_ctx other) ENTT_NOEXCEPT {
- internal::meta_context::global() = other.ctx;
- }
- private:
- internal::meta_type_node **ctx{&internal::meta_context::local()};
- };
- } // namespace entt
- #endif
- // #include "meta/factory.hpp"
- #ifndef ENTT_META_FACTORY_HPP
- #define ENTT_META_FACTORY_HPP
- #include <algorithm>
- #include <cstddef>
- #include <functional>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- // #include "../core/fwd.hpp"
- // #include "../core/type_info.hpp"
- // #include "../core/type_traits.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 {
- /*! @brief Empty class type used to request the _as ref_ policy. */
- struct as_ref_t {
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- template<typename Type>
- static constexpr bool value = std::is_reference_v<Type> && !std::is_const_v<std::remove_reference_t<Type>>;
- /**
- * Internal details not to be documented.
- * @endcond
- */
- };
- /*! @brief Empty class type used to request the _as cref_ policy. */
- struct as_cref_t {
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- template<typename Type>
- static constexpr bool value = std::is_reference_v<Type>;
- /**
- * Internal details not to be documented.
- * @endcond
- */
- };
- /*! @brief Empty class type used to request the _as-is_ policy. */
- struct as_is_t {
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- template<typename>
- static constexpr bool value = true;
- /**
- * Internal details not to be documented.
- * @endcond
- */
- };
- /*! @brief Empty class type used to request the _as void_ policy. */
- struct as_void_t {
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- template<typename>
- static constexpr bool value = true;
- /**
- * Internal details not to be documented.
- * @endcond
- */
- };
- } // namespace entt
- #endif
- // #include "range.hpp"
- // #include "utility.hpp"
- #ifndef ENTT_META_UTILITY_HPP
- #define ENTT_META_UTILITY_HPP
- #include <cstddef>
- #include <functional>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- // #include "../core/type_traits.hpp"
- // #include "meta.hpp"
- // #include "node.hpp"
- // #include "policy.hpp"
- namespace entt {
- /*! @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> {
- /*! @brief Meta function return type. */
- using return_type = Ret;
- /*! @brief Meta function arguments. */
- using args_type = std::conditional_t<std::is_base_of_v<Class, Type>, type_list<Args...>, type_list<const Class &, Args...>>;
- /*! @brief True if the meta function is const, false otherwise. */
- static constexpr auto is_const = true;
- /*! @brief True if the meta function is static, false otherwise. */
- static constexpr auto is_static = !std::is_base_of_v<Class, Type>;
- };
- /**
- * @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...)> {
- /*! @brief Meta function return type. */
- using return_type = Ret;
- /*! @brief Meta function arguments. */
- using args_type = std::conditional_t<std::is_base_of_v<Class, Type>, type_list<Args...>, type_list<Class &, Args...>>;
- /*! @brief True if the meta function is const, false otherwise. */
- static constexpr auto is_const = false;
- /*! @brief True if the meta function is static, false otherwise. */
- static constexpr auto is_static = !std::is_base_of_v<Class, Type>;
- };
- /**
- * @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::*> {
- /*! @brief Meta data return type. */
- using return_type = Ret &;
- /*! @brief Meta data arguments. */
- using args_type = std::conditional_t<std::is_base_of_v<Class, Type>, type_list<>, type_list<Class &>>;
- /*! @brief True if the meta data is const, false otherwise. */
- static constexpr auto is_const = false;
- /*! @brief True if the meta data is static, false otherwise. */
- static constexpr auto is_static = !std::is_base_of_v<Class, Type>;
- };
- /**
- * @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...)> {
- /*! @brief Meta function return type. */
- using return_type = Ret;
- /*! @brief Meta function arguments. */
- using args_type = std::conditional_t<std::is_base_of_v<std::remove_cv_t<std::remove_reference_t<MaybeType>>, Type>, type_list<Args...>, type_list<MaybeType, Args...>>;
- /*! @brief True if the meta function is const, false otherwise. */
- static constexpr auto is_const = std::is_base_of_v<std::remove_cv_t<std::remove_reference_t<MaybeType>>, Type> && std::is_const_v<std::remove_reference_t<MaybeType>>;
- /*! @brief True if the meta function is static, false otherwise. */
- static constexpr auto is_static = !std::is_base_of_v<std::remove_cv_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 (*)()> {
- /*! @brief Meta function return type. */
- using return_type = Ret;
- /*! @brief Meta function arguments. */
- using args_type = type_list<>;
- /*! @brief True if the meta function is const, false otherwise. */
- static constexpr auto is_const = false;
- /*! @brief True if the meta function is static, false otherwise. */
- static constexpr auto is_static = true;
- };
- /**
- * @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>
- 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.
- * @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_is_t, typename Type>
- meta_any meta_dispatch([[maybe_unused]] Type &&value) {
- if constexpr(std::is_same_v<Policy, as_void_t>) {
- return meta_any{std::in_place_type<void>};
- } else if constexpr(std::is_same_v<Policy, as_ref_t>) {
- return meta_any{std::in_place_type<Type>, std::forward<Type>(value)};
- } else if constexpr(std::is_same_v<Policy, as_cref_t>) {
- static_assert(std::is_lvalue_reference_v<Type>, "Invalid type");
- return meta_any{std::in_place_type<const std::remove_reference_t<Type> &>, std::as_const(value)};
- } else {
- static_assert(std::is_same_v<Policy, as_is_t>, "Policy not supported");
- return meta_any{std::forward<Type>(value)};
- }
- }
- /**
- * @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.
- * @return The meta type of the i-th element of the list of arguments.
- */
- template<typename Type>
- [[nodiscard]] static meta_type meta_arg(const std::size_t index) ENTT_NOEXCEPT {
- return internal::meta_arg_node(Type{}, 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_same_v<decltype(Data), Type> && !std::is_same_v<decltype(Data), std::nullptr_t>) {
- 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 {
- 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_is_t>
- [[nodiscard]] meta_any meta_getter([[maybe_unused]] 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_cv_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>(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>(std::invoke(Data, *fallback));
- }
- }
- }
- return meta_any{};
- } else if constexpr(std::is_pointer_v<decltype(Data)>) {
- if constexpr(std::is_array_v<std::remove_pointer_t<decltype(Data)>>) {
- return meta_any{};
- } else {
- return meta_dispatch<Policy>(*Data);
- }
- } else {
- return meta_dispatch<Policy>(Data);
- }
- }
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- namespace internal {
- template<typename Type, typename Policy, typename Candidate, typename... Args>
- [[nodiscard]] meta_any meta_invoke_with_args(Candidate &&candidate, Args &&...args) {
- if constexpr(std::is_same_v<std::invoke_result_t<decltype(candidate), Args...>, void>) {
- std::invoke(candidate, args...);
- return meta_any{std::in_place_type<void>};
- } else {
- return meta_dispatch<Policy>(std::invoke(candidate, args...));
- }
- }
- template<typename Type, typename Policy, typename Candidate, std::size_t... Index>
- [[nodiscard]] meta_any meta_invoke([[maybe_unused]] meta_handle instance, Candidate &&candidate, [[maybe_unused]] meta_any *args, std::index_sequence<Index...>) {
- using descriptor = meta_function_helper_t<Type, std::remove_reference_t<Candidate>>;
- 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<Type, Policy>(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<Type, Policy>(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<Type, Policy>(std::forward<Candidate>(candidate), (args + Index)->cast<type_list_element_t<Index, typename descriptor::args_type>>()...);
- }
- }
- return meta_any{};
- }
- template<typename Type, typename... Args, std::size_t... Index>
- [[nodiscard]] meta_any meta_construct(meta_any *const args, std::index_sequence<Index...>) {
- if(((args + Index)->allow_cast<Args>() && ...)) {
- return meta_any{std::in_place_type<Type>, (args + Index)->cast<Args>()...};
- }
- return meta_any{};
- }
- } // namespace internal
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /**
- * @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_is_t, typename Candidate>
- [[nodiscard]] meta_any meta_invoke([[maybe_unused]] meta_handle instance, Candidate &&candidate, [[maybe_unused]] meta_any *const args) {
- return internal::meta_invoke<Type, Policy>(std::move(instance), 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_is_t>
- [[nodiscard]] meta_any meta_invoke(meta_handle instance, meta_any *const args) {
- return internal::meta_invoke<Type, Policy>(std::move(instance), 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.
- * @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 internal::meta_construct<Type, Args...>(args, std::index_sequence_for<Args...>{});
- }
- /**
- * @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 args Parameters to use to _invoke_ the object.
- * @param candidate The actual object to _invoke_.
- * @return A meta any containing the returned value, if any.
- */
- template<typename Type, typename Policy = as_is_t, typename Candidate>
- [[nodiscard]] meta_any meta_construct(Candidate &&candidate, meta_any *const args) {
- if constexpr(meta_function_helper_t<Type, Candidate>::is_static) {
- return internal::meta_invoke<Type, Policy>({}, std::forward<Candidate>(candidate), args, std::make_index_sequence<meta_function_helper_t<Type, std::remove_reference_t<Candidate>>::args_type::size>{});
- } else {
- 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 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_is_t>
- [[nodiscard]] meta_any meta_construct(meta_any *const args) {
- return meta_construct<Type, Policy>(Candidate, args);
- }
- } // namespace entt
- #endif
- namespace entt {
- /**
- * @brief Meta factory to be used for reflection purposes.
- *
- * The meta factory is an utility class used to reflect types, data members and
- * functions of all sorts. This class ensures that the underlying web of types
- * is built correctly and performs some checks in debug mode to ensure that
- * there are no subtle errors at runtime.
- */
- template<typename...>
- class meta_factory;
- /**
- * @brief Extended meta factory to be used for reflection purposes.
- * @tparam Type Reflected type for which the factory was created.
- * @tparam Spec Property specialization pack used to disambiguate overloads.
- */
- template<typename Type, typename... Spec>
- class meta_factory<Type, Spec...>: public meta_factory<Type> {
- void link_prop_if_required(internal::meta_prop_node &node) ENTT_NOEXCEPT {
- if(meta_range<internal::meta_prop_node *, internal::meta_prop_node> range{*ref}; std::find(range.cbegin(), range.cend(), &node) == range.cend()) {
- ENTT_ASSERT(std::find_if(range.cbegin(), range.cend(), [&node](const auto *curr) { return curr->id == node.id; }) == range.cend(), "Duplicate identifier");
- node.next = *ref;
- *ref = &node;
- }
- }
- template<std::size_t Step = 0, typename... Property, typename... Other>
- void unroll(choice_t<2>, std::tuple<Property...> property, Other &&...other) ENTT_NOEXCEPT {
- std::apply([this](auto &&...curr) { (this->unroll<Step>(choice<2>, std::forward<Property>(curr)...)); }, property);
- unroll<Step + sizeof...(Property)>(choice<2>, std::forward<Other>(other)...);
- }
- template<std::size_t Step = 0, typename... Property, typename... Other>
- void unroll(choice_t<1>, std::pair<Property...> property, Other &&...other) ENTT_NOEXCEPT {
- assign<Step>(std::move(property.first), std::move(property.second));
- unroll<Step + 1>(choice<2>, std::forward<Other>(other)...);
- }
- template<std::size_t Step = 0, typename Property, typename... Other>
- void unroll(choice_t<0>, Property &&property, Other &&...other) ENTT_NOEXCEPT {
- assign<Step>(std::forward<Property>(property));
- unroll<Step + 1>(choice<2>, std::forward<Other>(other)...);
- }
- template<std::size_t>
- void unroll(choice_t<0>) ENTT_NOEXCEPT {}
- template<std::size_t = 0>
- void assign(meta_any key, meta_any value = {}) {
- static meta_any property[2u]{};
- static internal::meta_prop_node node{
- nullptr,
- property[0u],
- property[1u]
- // tricks clang-format
- };
- property[0u] = std::move(key);
- property[1u] = std::move(value);
- link_prop_if_required(node);
- }
- public:
- /**
- * @brief Constructs an extended factory from a given node.
- * @param target The underlying node to which to assign the properties.
- */
- meta_factory(internal::meta_prop_node **target) ENTT_NOEXCEPT
- : ref{target} {}
- /**
- * @brief Assigns a property to the last meta object created.
- *
- * Both the key and the value (if any) must be at least copy constructible.
- *
- * @tparam PropertyOrKey Type of the property or property key.
- * @tparam Value Optional type of the property value.
- * @param property_or_key Property or property key.
- * @param value Optional property value.
- * @return A meta factory for the parent type.
- */
- template<typename PropertyOrKey, typename... Value>
- meta_factory<Type> prop(PropertyOrKey &&property_or_key, Value &&...value) {
- if constexpr(sizeof...(Value) == 0) {
- unroll(choice<2>, std::forward<PropertyOrKey>(property_or_key));
- } else {
- assign(std::forward<PropertyOrKey>(property_or_key), std::forward<Value>(value)...);
- }
- return {};
- }
- /**
- * @brief Assigns properties to the last meta object created.
- *
- * Both key and value (if any) must be at least copy constructible.
- *
- * @tparam Property Types of the properties.
- * @param property Properties to assign to the last meta object created.
- * @return A meta factory for the parent type.
- */
- template<typename... Property>
- meta_factory<Type> props(Property... property) {
- unroll(choice<2>, std::forward<Property>(property)...);
- return {};
- }
- private:
- internal::meta_prop_node **ref;
- };
- /**
- * @brief Basic meta factory to be used for reflection purposes.
- * @tparam Type Reflected type for which the factory was created.
- */
- template<typename Type>
- class meta_factory<Type> {
- void link_base_if_required(internal::meta_base_node &node) ENTT_NOEXCEPT {
- if(meta_range<internal::meta_base_node *, internal::meta_base_node> range{owner->base}; std::find(range.cbegin(), range.cend(), &node) == range.cend()) {
- node.next = owner->base;
- owner->base = &node;
- }
- }
- void link_conv_if_required(internal::meta_conv_node &node) ENTT_NOEXCEPT {
- if(meta_range<internal::meta_conv_node *, internal::meta_conv_node> range{owner->conv}; std::find(range.cbegin(), range.cend(), &node) == range.cend()) {
- node.next = owner->conv;
- owner->conv = &node;
- }
- }
- void link_ctor_if_required(internal::meta_ctor_node &node) ENTT_NOEXCEPT {
- if(meta_range<internal::meta_ctor_node *, internal::meta_ctor_node> range{owner->ctor}; std::find(range.cbegin(), range.cend(), &node) == range.cend()) {
- node.next = owner->ctor;
- owner->ctor = &node;
- }
- }
- void link_data_if_required(const id_type id, internal::meta_data_node &node) ENTT_NOEXCEPT {
- meta_range<internal::meta_data_node *, internal::meta_data_node> range{owner->data};
- ENTT_ASSERT(std::find_if(range.cbegin(), range.cend(), [id, &node](const auto *curr) { return curr != &node && curr->id == id; }) == range.cend(), "Duplicate identifier");
- node.id = id;
- if(std::find(range.cbegin(), range.cend(), &node) == range.cend()) {
- node.next = owner->data;
- owner->data = &node;
- }
- }
- void link_func_if_required(const id_type id, internal::meta_func_node &node) ENTT_NOEXCEPT {
- node.id = id;
- if(meta_range<internal::meta_func_node *, internal::meta_func_node> range{owner->func}; std::find(range.cbegin(), range.cend(), &node) == range.cend()) {
- node.next = owner->func;
- owner->func = &node;
- }
- }
- template<typename Setter, auto Getter, typename Policy, std::size_t... Index>
- auto data(const id_type id, std::index_sequence<Index...>) ENTT_NOEXCEPT {
- using data_type = std::invoke_result_t<decltype(Getter), Type &>;
- using args_type = type_list<typename meta_function_helper_t<Type, decltype(value_list_element_v<Index, Setter>)>::args_type...>;
- static_assert(Policy::template value<data_type>, "Invalid return type for the given policy");
- static internal::meta_data_node node{
- {},
- /* this is never static */
- (std::is_member_object_pointer_v<decltype(value_list_element_v<Index, Setter>)> && ... && std::is_const_v<std::remove_reference_t<data_type>>) ? internal::meta_traits::is_const : internal::meta_traits::is_none,
- nullptr,
- nullptr,
- Setter::size,
- internal::meta_node<std::remove_cv_t<std::remove_reference_t<data_type>>>::resolve(),
- &meta_arg<type_list<type_list_element_t<type_list_element_t<Index, args_type>::size != 1u, type_list_element_t<Index, args_type>>...>>,
- [](meta_handle instance, meta_any value) -> bool { return (meta_setter<Type, value_list_element_v<Index, Setter>>(*instance.operator->(), value.as_ref()) || ...); },
- &meta_getter<Type, Getter, Policy>
- // tricks clang-format
- };
- link_data_if_required(id, node);
- return meta_factory<Type, Setter, std::integral_constant<decltype(Getter), Getter>>{&node.prop};
- }
- public:
- /*! @brief Default constructor. */
- meta_factory() ENTT_NOEXCEPT
- : owner{internal::meta_node<Type>::resolve()} {}
- /**
- * @brief Makes a meta type _searchable_.
- * @param id Optional unique identifier.
- * @return An extended meta factory for the given type.
- */
- auto type(const id_type id = type_hash<Type>::value()) ENTT_NOEXCEPT {
- meta_range<internal::meta_type_node *, internal::meta_type_node> range{*internal::meta_context::global()};
- ENTT_ASSERT(std::find_if(range.cbegin(), range.cend(), [id, this](const auto *curr) { return curr != owner && curr->id == id; }) == range.cend(), "Duplicate identifier");
- owner->id = id;
- if(std::find(range.cbegin(), range.cend(), owner) == range.cend()) {
- owner->next = *internal::meta_context::global();
- *internal::meta_context::global() = owner;
- }
- return meta_factory<Type, Type>{&owner->prop};
- }
- /**
- * @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>
- auto base() ENTT_NOEXCEPT {
- static_assert(!std::is_same_v<Type, Base> && std::is_base_of_v<Base, Type>, "Invalid base type");
- static internal::meta_base_node node{
- nullptr,
- internal::meta_node<Base>::resolve(),
- [](meta_any other) ENTT_NOEXCEPT -> meta_any {
- if(auto *ptr = other.data(); ptr) {
- return forward_as_meta(*static_cast<Base *>(static_cast<Type *>(ptr)));
- }
- return forward_as_meta(*static_cast<const Base *>(static_cast<const Type *>(std::as_const(other).data())));
- }
- // tricks clang-format
- };
- link_base_if_required(node);
- return meta_factory<Type>{};
- }
- /**
- * @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() ENTT_NOEXCEPT {
- static internal::meta_conv_node node{
- nullptr,
- internal::meta_node<std::remove_cv_t<std::remove_reference_t<std::invoke_result_t<decltype(Candidate), Type &>>>>::resolve(),
- [](const meta_any &instance) -> meta_any {
- return forward_as_meta(std::invoke(Candidate, *static_cast<const Type *>(instance.data())));
- }
- // tricks clang-format
- };
- link_conv_if_required(node);
- return meta_factory<Type>{};
- }
- /**
- * @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>
- auto conv() ENTT_NOEXCEPT {
- static internal::meta_conv_node node{
- nullptr,
- internal::meta_node<std::remove_cv_t<std::remove_reference_t<To>>>::resolve(),
- [](const meta_any &instance) -> meta_any { return forward_as_meta(static_cast<To>(*static_cast<const Type *>(instance.data()))); }
- // tricks clang-format
- };
- link_conv_if_required(node);
- return meta_factory<Type>{};
- }
- /**
- * @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 An extended meta factory for the parent type.
- */
- template<auto Candidate, typename Policy = as_is_t>
- auto ctor() ENTT_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_cv_t<std::remove_reference_t<typename descriptor::return_type>>, Type>, "The function doesn't return an object of the required type");
- static internal::meta_ctor_node node{
- nullptr,
- descriptor::args_type::size,
- &meta_arg<typename descriptor::args_type>,
- &meta_construct<Type, Candidate, Policy>
- // tricks clang-format
- };
- link_ctor_if_required(node);
- return meta_factory<Type>{};
- }
- /**
- * @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 An extended meta factory for the parent type.
- */
- template<typename... Args>
- auto ctor() ENTT_NOEXCEPT {
- using descriptor = meta_function_helper_t<Type, Type (*)(Args...)>;
- static internal::meta_ctor_node node{
- nullptr,
- descriptor::args_type::size,
- &meta_arg<typename descriptor::args_type>,
- &meta_construct<Type, Args...>
- // tricks clang-format
- };
- link_ctor_if_required(node);
- return meta_factory<Type>{};
- }
- /**
- * @brief Assigns a meta destructor to a meta type.
- *
- * Both free functions and member functions can be assigned to meta types in
- * the role of destructors.<br/>
- * The signature of a free function should be identical to the following:
- *
- * @code{.cpp}
- * void(Type &);
- * @endcode
- *
- * Member functions should not take arguments instead.<br/>
- * The purpose is to give users the ability to free up resources that
- * require special treatment before an object is actually destroyed.
- *
- * @tparam Func The actual function to use as a destructor.
- * @return A meta factory for the parent type.
- */
- template<auto Func>
- auto dtor() ENTT_NOEXCEPT {
- static_assert(std::is_invocable_v<decltype(Func), Type &>, "The function doesn't accept an object of the type provided");
- owner->dtor = [](void *instance) { std::invoke(Func, *static_cast<Type *>(instance)); };
- return meta_factory<Type>{};
- }
- /**
- * @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.
- * @return An extended meta factory for the parent type.
- */
- template<auto Data, typename Policy = as_is_t>
- auto data(const id_type id) ENTT_NOEXCEPT {
- if constexpr(std::is_member_object_pointer_v<decltype(Data)>) {
- using data_type = std::remove_reference_t<std::invoke_result_t<decltype(Data), Type &>>;
- static internal::meta_data_node node{
- {},
- /* this is never static */
- std::is_const_v<data_type> ? internal::meta_traits::is_const : internal::meta_traits::is_none,
- nullptr,
- nullptr,
- 1u,
- internal::meta_node<std::remove_const_t<data_type>>::resolve(),
- &meta_arg<type_list<std::remove_const_t<data_type>>>,
- &meta_setter<Type, Data>,
- &meta_getter<Type, Data, Policy>
- // tricks clang-format
- };
- link_data_if_required(id, node);
- return meta_factory<Type, std::integral_constant<decltype(Data), Data>, std::integral_constant<decltype(Data), Data>>{&node.prop};
- } else {
- using data_type = std::remove_reference_t<std::remove_pointer_t<decltype(Data)>>;
- static internal::meta_data_node node{
- {},
- ((std::is_same_v<Type, std::remove_const_t<data_type>> || std::is_const_v<data_type>) ? internal::meta_traits::is_const : internal::meta_traits::is_none) | internal::meta_traits::is_static,
- nullptr,
- nullptr,
- 1u,
- internal::meta_node<std::remove_const_t<data_type>>::resolve(),
- &meta_arg<type_list<std::remove_const_t<data_type>>>,
- &meta_setter<Type, Data>,
- &meta_getter<Type, Data, Policy>
- // tricks clang-format
- };
- link_data_if_required(id, node);
- return meta_factory<Type, std::integral_constant<decltype(Data), Data>>{&node.prop};
- }
- }
- /**
- * @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.
- * @return An extended meta factory for the parent type.
- */
- template<auto Setter, auto Getter, typename Policy = as_is_t>
- auto data(const id_type id) ENTT_NOEXCEPT {
- using data_type = std::invoke_result_t<decltype(Getter), Type &>;
- static_assert(Policy::template value<data_type>, "Invalid return type for the given policy");
- if constexpr(std::is_same_v<decltype(Setter), std::nullptr_t>) {
- static internal::meta_data_node node{
- {},
- /* this is never static */
- internal::meta_traits::is_const,
- nullptr,
- nullptr,
- 0u,
- internal::meta_node<std::remove_cv_t<std::remove_reference_t<data_type>>>::resolve(),
- &meta_arg<type_list<>>,
- &meta_setter<Type, Setter>,
- &meta_getter<Type, Getter, Policy>
- // tricks clang-format
- };
- link_data_if_required(id, node);
- return meta_factory<Type, std::integral_constant<decltype(Setter), Setter>, std::integral_constant<decltype(Getter), Getter>>{&node.prop};
- } else {
- using args_type = typename meta_function_helper_t<Type, decltype(Setter)>::args_type;
- static internal::meta_data_node node{
- {},
- /* this is never static nor const */
- internal::meta_traits::is_none,
- nullptr,
- nullptr,
- 1u,
- internal::meta_node<std::remove_cv_t<std::remove_reference_t<data_type>>>::resolve(),
- &meta_arg<type_list<type_list_element_t<args_type::size != 1u, args_type>>>,
- &meta_setter<Type, Setter>,
- &meta_getter<Type, Getter, Policy>
- // tricks clang-format
- };
- link_data_if_required(id, node);
- return meta_factory<Type, std::integral_constant<decltype(Setter), Setter>, std::integral_constant<decltype(Getter), Getter>>{&node.prop};
- }
- }
- /**
- * @brief Assigns a meta data to a meta type by means of its setters and
- * getter.
- *
- * Multi-setter support for meta data members. All setters are tried in the
- * order of definition before returning to the caller.<br/>
- * Setters can be either free functions, member functions or a mix of them
- * and are provided via a `value_list` type.
- *
- * @sa data
- *
- * @tparam Setter The actual functions to use as setters.
- * @tparam Getter The actual getter function.
- * @tparam Policy Optional policy (no policy set by default).
- * @param id Unique identifier.
- * @return An extended meta factory for the parent type.
- */
- template<typename Setter, auto Getter, typename Policy = as_is_t>
- auto data(const id_type id) ENTT_NOEXCEPT {
- return data<Setter, Getter, Policy>(id, std::make_index_sequence<Setter::size>{});
- }
- /**
- * @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.
- * @return An extended meta factory for the parent type.
- */
- template<auto Candidate, typename Policy = as_is_t>
- auto func(const id_type id) ENTT_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 internal::meta_func_node node{
- {},
- (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),
- nullptr,
- nullptr,
- descriptor::args_type::size,
- internal::meta_node<std::conditional_t<std::is_same_v<Policy, as_void_t>, void, std::remove_cv_t<std::remove_reference_t<typename descriptor::return_type>>>>::resolve(),
- &meta_arg<typename descriptor::args_type>,
- &meta_invoke<Type, Candidate, Policy>
- // tricks clang-format
- };
- link_func_if_required(id, node);
- return meta_factory<Type, std::integral_constant<decltype(Candidate), Candidate>>{&node.prop};
- }
- private:
- internal::meta_type_node *owner;
- };
- /**
- * @brief Utility function to use for reflection.
- *
- * This is the point from which everything starts.<br/>
- * By invoking this function with a type that is not yet reflected, a meta type
- * is created to which it will be possible to attach meta objects through a
- * dedicated factory.
- *
- * @tparam Type Type to reflect.
- * @return A meta factory for the given type.
- */
- template<typename Type>
- [[nodiscard]] auto meta() ENTT_NOEXCEPT {
- auto *const node = internal::meta_node<Type>::resolve();
- // extended meta factory to allow assigning properties to opaque meta types
- return meta_factory<Type, Type>{&node->prop};
- }
- /**
- * @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 list of searchable types.
- *
- * @param id Unique identifier.
- */
- inline void meta_reset(const id_type id) ENTT_NOEXCEPT {
- auto clear_chain = [](auto **curr, auto... member) {
- for(; *curr; *curr = std::exchange((*curr)->next, nullptr)) {
- if constexpr(sizeof...(member) != 0u) {
- static_assert(sizeof...(member) == 1u, "Assert in defense of the future me");
- for(auto **sub = (&((*curr)->*member), ...); *sub; *sub = std::exchange((*sub)->next, nullptr)) {}
- }
- }
- };
- for(auto **it = internal::meta_context::global(); *it; it = &(*it)->next) {
- if(auto *node = *it; node->id == id) {
- clear_chain(&node->prop);
- clear_chain(&node->base);
- clear_chain(&node->conv);
- clear_chain(&node->ctor);
- clear_chain(&node->data, &internal::meta_data_node::prop);
- clear_chain(&node->func, &internal::meta_func_node::prop);
- node->id = {};
- node->dtor = nullptr;
- *it = std::exchange(node->next, nullptr);
- break;
- }
- }
- }
- /**
- * @brief Resets a type and all its parts.
- *
- * @sa meta_reset
- *
- * @tparam Type Type to reset.
- */
- template<typename Type>
- void meta_reset() ENTT_NOEXCEPT {
- meta_reset(internal::meta_node<Type>::resolve()->id);
- }
- /**
- * @brief Resets all searchable types.
- *
- * @sa meta_reset
- */
- inline void meta_reset() ENTT_NOEXCEPT {
- while(*internal::meta_context::global()) {
- meta_reset((*internal::meta_context::global())->id);
- }
- }
- } // namespace entt
- #endif
- // #include "meta/meta.hpp"
- #ifndef ENTT_META_META_HPP
- #define ENTT_META_META_HPP
- #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 "adl_pointer.hpp"
- // #include "ctx.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() ENTT_NOEXCEPT = default;
- /**
- * @brief Construct a proxy object for sequence containers.
- * @tparam Type Type of container to wrap.
- * @param instance The container to wrap.
- */
- template<typename Type>
- meta_sequence_container(std::in_place_type_t<Type>, any instance) ENTT_NOEXCEPT
- : value_type_node{internal::meta_node<std::remove_cv_t<std::remove_reference_t<typename Type::value_type>>>::resolve()},
- size_fn{&meta_sequence_container_traits<Type>::size},
- resize_fn{&meta_sequence_container_traits<Type>::resize},
- iter_fn{&meta_sequence_container_traits<Type>::iter},
- insert_fn{&meta_sequence_container_traits<Type>::insert},
- erase_fn{&meta_sequence_container_traits<Type>::erase},
- storage{std::move(instance)} {}
- [[nodiscard]] inline meta_type value_type() const ENTT_NOEXCEPT;
- [[nodiscard]] inline size_type size() const ENTT_NOEXCEPT;
- inline bool resize(const size_type);
- inline bool clear();
- [[nodiscard]] inline iterator begin();
- [[nodiscard]] inline iterator end();
- inline iterator insert(iterator, meta_any);
- inline iterator erase(iterator);
- [[nodiscard]] inline meta_any operator[](const size_type);
- [[nodiscard]] inline explicit operator bool() const ENTT_NOEXCEPT;
- private:
- internal::meta_type_node *value_type_node = nullptr;
- size_type (*size_fn)(const any &) ENTT_NOEXCEPT = nullptr;
- bool (*resize_fn)(any &, size_type) = nullptr;
- iterator (*iter_fn)(any &, const bool) = nullptr;
- iterator (*insert_fn)(any &, const std::ptrdiff_t, meta_any &) = nullptr;
- iterator (*erase_fn)(any &, const std::ptrdiff_t) = nullptr;
- any storage{};
- };
- /*! @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() ENTT_NOEXCEPT = default;
- /**
- * @brief Construct a proxy object for associative containers.
- * @tparam Type Type of container to wrap.
- * @param instance The container to wrap.
- */
- template<typename Type>
- meta_associative_container(std::in_place_type_t<Type>, any instance) ENTT_NOEXCEPT
- : key_only_container{meta_associative_container_traits<Type>::key_only},
- key_type_node{internal::meta_node<std::remove_cv_t<std::remove_reference_t<typename Type::key_type>>>::resolve()},
- mapped_type_node{nullptr},
- value_type_node{internal::meta_node<std::remove_cv_t<std::remove_reference_t<typename Type::value_type>>>::resolve()},
- size_fn{&meta_associative_container_traits<Type>::size},
- clear_fn{&meta_associative_container_traits<Type>::clear},
- iter_fn{&meta_associative_container_traits<Type>::iter},
- insert_fn{&meta_associative_container_traits<Type>::insert},
- erase_fn{&meta_associative_container_traits<Type>::erase},
- find_fn{&meta_associative_container_traits<Type>::find},
- storage{std::move(instance)} {
- if constexpr(!meta_associative_container_traits<Type>::key_only) {
- mapped_type_node = internal::meta_node<std::remove_cv_t<std::remove_reference_t<typename Type::mapped_type>>>::resolve();
- }
- }
- [[nodiscard]] inline bool key_only() const ENTT_NOEXCEPT;
- [[nodiscard]] inline meta_type key_type() const ENTT_NOEXCEPT;
- [[nodiscard]] inline meta_type mapped_type() const ENTT_NOEXCEPT;
- [[nodiscard]] inline meta_type value_type() const ENTT_NOEXCEPT;
- [[nodiscard]] inline size_type size() const ENTT_NOEXCEPT;
- inline bool clear();
- [[nodiscard]] inline iterator begin();
- [[nodiscard]] inline iterator end();
- inline bool insert(meta_any, meta_any);
- inline bool erase(meta_any);
- [[nodiscard]] inline iterator find(meta_any);
- [[nodiscard]] inline explicit operator bool() const ENTT_NOEXCEPT;
- private:
- bool key_only_container{};
- internal::meta_type_node *key_type_node = nullptr;
- internal::meta_type_node *mapped_type_node = nullptr;
- internal::meta_type_node *value_type_node = nullptr;
- size_type (*size_fn)(const any &) ENTT_NOEXCEPT = nullptr;
- bool (*clear_fn)(any &) = nullptr;
- iterator (*iter_fn)(any &, const bool) = nullptr;
- bool (*insert_fn)(any &, meta_any &, meta_any &) = nullptr;
- bool (*erase_fn)(any &, meta_any &) = nullptr;
- iterator (*find_fn)(any &, meta_any &) = nullptr;
- any storage{};
- };
- /*! @brief Opaque wrapper for values of any type. */
- class meta_any {
- enum class operation : std::uint8_t {
- deref,
- seq,
- assoc
- };
- using vtable_type = void(const operation, const any &, void *);
- template<typename Type>
- static void basic_vtable([[maybe_unused]] const operation op, [[maybe_unused]] const any &value, [[maybe_unused]] void *other) {
- static_assert(std::is_same_v<std::remove_cv_t<std::remove_reference_t<Type>>, Type>, "Invalid type");
- if constexpr(!std::is_void_v<Type>) {
- switch(op) {
- case operation::deref:
- if constexpr(is_meta_pointer_like_v<Type>) {
- if constexpr(std::is_function_v<std::remove_const_t<typename std::pointer_traits<Type>::element_type>>) {
- *static_cast<meta_any *>(other) = any_cast<Type>(value);
- } else if constexpr(!std::is_same_v<std::remove_const_t<typename std::pointer_traits<Type>::element_type>, void>) {
- using in_place_type = decltype(adl_meta_pointer_like<Type>::dereference(any_cast<const Type &>(value)));
- if constexpr(std::is_constructible_v<bool, Type>) {
- if(const auto &pointer_like = any_cast<const Type &>(value); pointer_like) {
- static_cast<meta_any *>(other)->emplace<in_place_type>(adl_meta_pointer_like<Type>::dereference(pointer_like));
- }
- } else {
- static_cast<meta_any *>(other)->emplace<in_place_type>(adl_meta_pointer_like<Type>::dereference(any_cast<const Type &>(value)));
- }
- }
- }
- break;
- case operation::seq:
- if constexpr(is_complete_v<meta_sequence_container_traits<Type>>) {
- *static_cast<meta_sequence_container *>(other) = {std::in_place_type<Type>, std::move(const_cast<any &>(value))};
- }
- break;
- case operation::assoc:
- if constexpr(is_complete_v<meta_associative_container_traits<Type>>) {
- *static_cast<meta_associative_container *>(other) = {std::in_place_type<Type>, std::move(const_cast<any &>(value))};
- }
- break;
- }
- }
- }
- void release() {
- if(node && node->dtor && storage.owner()) {
- node->dtor(storage.data());
- }
- }
- meta_any(const meta_any &other, any ref) ENTT_NOEXCEPT
- : storage{std::move(ref)},
- node{storage ? other.node : nullptr},
- vtable{storage ? other.vtable : &basic_vtable<void>} {}
- public:
- /*! @brief Default constructor. */
- meta_any() ENTT_NOEXCEPT
- : storage{},
- node{},
- vtable{&basic_vtable<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 meta_any(std::in_place_type_t<Type>, Args &&...args)
- : storage{std::in_place_type<Type>, std::forward<Args>(args)...},
- node{internal::meta_node<std::remove_cv_t<std::remove_reference_t<Type>>>::resolve()},
- vtable{&basic_vtable<std::remove_cv_t<std::remove_reference_t<Type>>>} {}
- /**
- * @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{std::in_place_type<std::remove_cv_t<std::remove_reference_t<Type>>>, std::forward<Type>(value)} {}
- /**
- * @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) ENTT_NOEXCEPT
- : storage{std::move(other.storage)},
- node{std::exchange(other.node, nullptr)},
- vtable{std::exchange(other.vtable, &basic_vtable<void>)} {}
- /*! @brief Frees the internal storage, whatever it means. */
- ~meta_any() {
- release();
- }
- /**
- * @brief Copy assignment operator.
- * @param other The instance to copy from.
- * @return This meta any object.
- */
- meta_any &operator=(const meta_any &other) {
- release();
- vtable = other.vtable;
- storage = other.storage;
- node = other.node;
- return *this;
- }
- /**
- * @brief Move assignment operator.
- * @param other The instance to move from.
- * @return This meta any object.
- */
- meta_any &operator=(meta_any &&other) ENTT_NOEXCEPT {
- release();
- vtable = std::exchange(other.vtable, &basic_vtable<void>);
- storage = std::move(other.storage);
- node = std::exchange(other.node, 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>
- 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::type */
- [[nodiscard]] inline meta_type type() const ENTT_NOEXCEPT;
- /*! @copydoc any::data */
- [[nodiscard]] const void *data() const ENTT_NOEXCEPT {
- return storage.data();
- }
- /*! @copydoc any::data */
- [[nodiscard]] void *data() ENTT_NOEXCEPT {
- return storage.data();
- }
- /**
- * @brief Invokes the underlying function, if possible.
- *
- * @sa meta_func::invoke
- *
- * @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(const id_type id, Args &&...args) const;
- /*! @copydoc invoke */
- template<typename... Args>
- meta_any invoke(const id_type id, Args &&...args);
- /**
- * @brief Sets the value of a given variable.
- *
- * The type of the value is such that a cast or conversion to the type of
- * the variable is possible. Otherwise, invoking the setter does nothing.
- *
- * @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(const 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(const id_type id) const;
- /*! @copydoc get */
- [[nodiscard]] meta_any get(const 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 {
- if(const auto &info = type_id<Type>(); node && *node->info == info) {
- return any_cast<Type>(&storage);
- } else if(node) {
- for(auto *it = node->base; it; it = it->next) {
- const auto as_const = it->cast(as_ref());
- if(const Type *base = as_const.template try_cast<Type>(); base) {
- return base;
- }
- }
- }
- return nullptr;
- }
- /*! @copydoc try_cast */
- template<typename Type>
- [[nodiscard]] Type *try_cast() {
- if(const auto &info = type_id<Type>(); node && *node->info == info) {
- return any_cast<Type>(&storage);
- } else if(node) {
- for(auto *it = node->base; it; it = it->next) {
- if(Type *base = it->cast(as_ref()).template try_cast<Type>(); base) {
- return base;
- }
- }
- }
- return nullptr;
- }
- /**
- * @brief Tries to cast an instance to a given type.
- *
- * The type of the instance must be such that the cast is possible.
- *
- * @warning
- * Attempting to perform an invalid cast results is undefined behavior.
- *
- * @tparam Type Type to which to cast the instance.
- * @return A reference to the contained instance.
- */
- template<typename Type>
- [[nodiscard]] 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]] 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 any object if there exists a viable conversion, 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 there exists a viable conversion, false otherwise.
- */
- [[nodiscard]] bool allow_cast(const meta_type &type) {
- if(auto other = std::as_const(*this).allow_cast(type); other) {
- if(other.storage.owner()) {
- std::swap(*this, other);
- }
- return true;
- }
- return false;
- }
- /**
- * @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 any object if there exists a viable conversion, an
- * invalid one otherwise.
- */
- template<typename Type>
- [[nodiscard]] meta_any allow_cast() const {
- const auto other = allow_cast(internal::meta_node<std::remove_cv_t<std::remove_reference_t<Type>>>::resolve());
- if constexpr(std::is_reference_v<Type> && !std::is_const_v<std::remove_reference_t<Type>>) {
- return other.storage.owner() ? other : meta_any{};
- } else {
- return other;
- }
- }
- /**
- * @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 there exists a viable conversion, false otherwise.
- */
- template<typename Type>
- bool allow_cast() {
- if(auto other = std::as_const(*this).allow_cast(internal::meta_node<std::remove_cv_t<std::remove_reference_t<Type>>>::resolve()); other) {
- if(other.storage.owner()) {
- std::swap(*this, other);
- return true;
- }
- return (static_cast<constness_as_t<any, std::remove_reference_t<const Type>> &>(storage).data() != nullptr);
- }
- return false;
- }
- /*! @copydoc any::emplace */
- template<typename Type, typename... Args>
- void emplace(Args &&...args) {
- release();
- vtable = &basic_vtable<std::remove_cv_t<std::remove_reference_t<Type>>>;
- storage.emplace<Type>(std::forward<Args>(args)...);
- node = internal::meta_node<std::remove_cv_t<std::remove_reference_t<Type>>>::resolve();
- }
- /*! @copydoc any::assign */
- bool assign(const meta_any &other);
- /*! @copydoc any::assign */
- bool assign(meta_any &&other);
- /*! @copydoc any::reset */
- void reset() {
- release();
- vtable = &basic_vtable<void>;
- storage.reset();
- node = nullptr;
- }
- /**
- * @brief Returns a sequence container proxy.
- * @return A sequence container proxy for the underlying object.
- */
- [[nodiscard]] meta_sequence_container as_sequence_container() ENTT_NOEXCEPT {
- any detached = storage.as_ref();
- meta_sequence_container proxy;
- vtable(operation::seq, detached, &proxy);
- return proxy;
- }
- /*! @copydoc as_sequence_container */
- [[nodiscard]] meta_sequence_container as_sequence_container() const ENTT_NOEXCEPT {
- any detached = storage.as_ref();
- meta_sequence_container proxy;
- vtable(operation::seq, detached, &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() ENTT_NOEXCEPT {
- any detached = storage.as_ref();
- meta_associative_container proxy;
- vtable(operation::assoc, detached, &proxy);
- return proxy;
- }
- /*! @copydoc as_associative_container */
- [[nodiscard]] meta_associative_container as_associative_container() const ENTT_NOEXCEPT {
- any detached = storage.as_ref();
- meta_associative_container proxy;
- vtable(operation::assoc, detached, &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 ENTT_NOEXCEPT {
- meta_any ret{};
- vtable(operation::deref, storage, &ret);
- return ret;
- }
- /**
- * @brief Returns false if a wrapper is invalid, true otherwise.
- * @return False if the wrapper is invalid, true otherwise.
- */
- [[nodiscard]] explicit operator bool() const ENTT_NOEXCEPT {
- return !(node == nullptr);
- }
- /*! @copydoc any::operator== */
- [[nodiscard]] bool operator==(const meta_any &other) const {
- return (!node && !other.node) || (node && other.node && *node->info == *other.node->info && storage == other.storage);
- }
- /*! @copydoc any::as_ref */
- [[nodiscard]] meta_any as_ref() ENTT_NOEXCEPT {
- return meta_any{*this, storage.as_ref()};
- }
- /*! @copydoc any::as_ref */
- [[nodiscard]] meta_any as_ref() const ENTT_NOEXCEPT {
- return meta_any{*this, storage.as_ref()};
- }
- /*! @copydoc any::owner */
- [[nodiscard]] bool owner() const ENTT_NOEXCEPT {
- return storage.owner();
- }
- private:
- any storage;
- internal::meta_type_node *node;
- vtable_type *vtable;
- };
- /**
- * @brief Checks if two wrappers differ in their content.
- * @param lhs A wrapper, either empty or not.
- * @param rhs A wrapper, either empty or not.
- * @return True if the two wrappers differ in their content, false otherwise.
- */
- [[nodiscard]] inline bool operator!=(const meta_any &lhs, const meta_any &rhs) ENTT_NOEXCEPT {
- return !(lhs == rhs);
- }
- /**
- * @brief Constructs a wrapper from a given type, passing it all arguments.
- * @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.
- * @return A properly initialized wrapper for an object of the given type.
- */
- template<typename Type, typename... Args>
- meta_any make_meta(Args &&...args) {
- return meta_any{std::in_place_type<Type>, std::forward<Args>(args)...};
- }
- /**
- * @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>
- meta_any forward_as_meta(Type &&value) {
- return meta_any{std::in_place_type<std::conditional_t<std::is_rvalue_reference_v<Type>, std::decay_t<Type>, Type>>, std::forward<Type>(value)};
- }
- /**
- * @brief Opaque pointers to instances of any type.
- *
- * A handle doesn't perform copies and isn't responsible for the contained
- * object. It doesn't prolong the lifetime of the pointed instance.<br/>
- * Handles are used to generate references to actual objects when needed.
- */
- struct meta_handle {
- /*! @brief Default constructor. */
- meta_handle() = default;
- /*! @brief Default copy constructor, deleted on purpose. */
- meta_handle(const meta_handle &) = delete;
- /*! @brief Default move constructor. */
- meta_handle(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 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) ENTT_NOEXCEPT
- : meta_handle{} {
- if constexpr(std::is_same_v<std::decay_t<Type>, meta_any>) {
- any = value.as_ref();
- } else {
- any.emplace<Type &>(value);
- }
- }
- /**
- * @brief Returns false if a handle is invalid, true otherwise.
- * @return False if the handle is invalid, true otherwise.
- */
- [[nodiscard]] explicit operator bool() const ENTT_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-> */
- [[nodiscard]] const meta_any *operator->() const {
- return &any;
- }
- private:
- meta_any any;
- };
- /*! @brief Opaque wrapper for properties of any type. */
- struct meta_prop {
- /*! @brief Node type. */
- using node_type = internal::meta_prop_node;
- /**
- * @brief Constructs an instance from a given node.
- * @param curr The underlying node with which to construct the instance.
- */
- meta_prop(const node_type *curr = nullptr) ENTT_NOEXCEPT
- : node{curr} {}
- /**
- * @brief Returns the stored key as a const reference.
- * @return A wrapper containing the key stored with the property.
- */
- [[nodiscard]] meta_any key() const {
- return node->id.as_ref();
- }
- /**
- * @brief Returns the stored value by copy.
- * @return A wrapper containing the value stored with the property.
- */
- [[nodiscard]] meta_any value() const {
- return node->value;
- }
- /**
- * @brief Returns true if an object is valid, false otherwise.
- * @return True if the object is valid, false otherwise.
- */
- [[nodiscard]] explicit operator bool() const ENTT_NOEXCEPT {
- return !(node == nullptr);
- }
- private:
- const node_type *node;
- };
- /*! @brief Opaque wrapper for data members. */
- struct meta_data {
- /*! @brief Node type. */
- using node_type = internal::meta_data_node;
- /*! @brief Unsigned integer type. */
- using size_type = typename node_type::size_type;
- /*! @copydoc meta_prop::meta_prop */
- meta_data(const node_type *curr = nullptr) ENTT_NOEXCEPT
- : node{curr} {}
- /*! @copydoc meta_type::id */
- [[nodiscard]] id_type id() const ENTT_NOEXCEPT {
- return node->id;
- }
- /**
- * @brief Returns the number of setters available.
- * @return The number of setters available.
- */
- [[nodiscard]] size_type arity() const ENTT_NOEXCEPT {
- return node->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 ENTT_NOEXCEPT {
- return !!(node->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 ENTT_NOEXCEPT {
- return !!(node->traits & internal::meta_traits::is_static);
- }
- /*! @copydoc meta_any::type */
- [[nodiscard]] inline meta_type type() const ENTT_NOEXCEPT;
- /**
- * @brief Sets the value of a given variable.
- *
- * It must be possible to cast the instance to the parent type of the data
- * member.<br/>
- * The type of the value is such that a cast or conversion to the type of
- * the variable is possible. Otherwise, invoking the setter does nothing.
- *
- * @tparam Type Type of value to assign.
- * @param instance An opaque instance of the underlying type.
- * @param value Parameter to use to set the underlying variable.
- * @return True in case of success, false otherwise.
- */
- template<typename Type>
- bool set(meta_handle instance, Type &&value) const {
- return node->set && node->set(std::move(instance), std::forward<Type>(value));
- }
- /**
- * @brief Gets the value of a given variable.
- *
- * It must be possible to cast the instance to the parent type of the data
- * member.
- *
- * @param instance An opaque instance of the underlying type.
- * @return A wrapper containing the value of the underlying variable.
- */
- [[nodiscard]] meta_any get(meta_handle instance) const {
- return node->get(std::move(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(const size_type index) const ENTT_NOEXCEPT;
- /**
- * @brief Returns a range to visit registered meta properties.
- * @return An iterable range to visit registered meta properties.
- */
- [[nodiscard]] meta_range<meta_prop> prop() const ENTT_NOEXCEPT {
- return node->prop;
- }
- /**
- * @brief Lookup function for registered meta properties.
- * @param key The key to use to search for a property.
- * @return The registered meta property for the given key, if any.
- */
- [[nodiscard]] meta_prop prop(meta_any key) const {
- for(auto curr: prop()) {
- if(curr.key() == key) {
- return curr;
- }
- }
- return nullptr;
- }
- /**
- * @brief Returns true if an object is valid, false otherwise.
- * @return True if the object is valid, false otherwise.
- */
- [[nodiscard]] explicit operator bool() const ENTT_NOEXCEPT {
- return !(node == nullptr);
- }
- private:
- const node_type *node;
- };
- /*! @brief Opaque wrapper for member functions. */
- struct meta_func {
- /*! @brief Node type. */
- using node_type = internal::meta_func_node;
- /*! @brief Unsigned integer type. */
- using size_type = typename node_type::size_type;
- /*! @copydoc meta_prop::meta_prop */
- meta_func(const node_type *curr = nullptr) ENTT_NOEXCEPT
- : node{curr} {}
- /*! @copydoc meta_type::id */
- [[nodiscard]] id_type id() const ENTT_NOEXCEPT {
- return node->id;
- }
- /**
- * @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 ENTT_NOEXCEPT {
- return node->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 ENTT_NOEXCEPT {
- return !!(node->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 ENTT_NOEXCEPT {
- return !!(node->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 ENTT_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(const size_type index) const ENTT_NOEXCEPT;
- /**
- * @brief Invokes the underlying function, if possible.
- *
- * To invoke a member function, the parameters must be such that a cast or
- * conversion to the required types is possible. Otherwise, an empty and
- * thus invalid wrapper is returned.<br/>
- * It must be possible to cast the instance to the parent type of the member
- * function.
- *
- * @param instance An opaque instance of 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.
- */
- meta_any invoke(meta_handle instance, meta_any *const args, const size_type sz) const {
- return sz == arity() ? node->invoke(std::move(instance), args) : meta_any{};
- }
- /**
- * @copybrief invoke
- *
- * @sa invoke
- *
- * @tparam Args Types of arguments to use to invoke the function.
- * @param instance An opaque instance of the underlying type.
- * @param args Parameters to use to invoke the function.
- * @return A wrapper containing the new instance, if any.
- */
- template<typename... Args>
- meta_any invoke(meta_handle instance, Args &&...args) const {
- meta_any arguments[sizeof...(Args) + 1u]{std::forward<Args>(args)...};
- return invoke(std::move(instance), arguments, sizeof...(Args));
- }
- /*! @copydoc meta_data::prop */
- [[nodiscard]] meta_range<meta_prop> prop() const ENTT_NOEXCEPT {
- return node->prop;
- }
- /**
- * @brief Lookup function for registered meta properties.
- * @param key The key to use to search for a property.
- * @return The registered meta property for the given key, if any.
- */
- [[nodiscard]] meta_prop prop(meta_any key) const {
- for(auto curr: prop()) {
- if(curr.key() == key) {
- return curr;
- }
- }
- return nullptr;
- }
- /**
- * @brief Returns true if an object is valid, false otherwise.
- * @return True if the object is valid, false otherwise.
- */
- [[nodiscard]] explicit operator bool() const ENTT_NOEXCEPT {
- return !(node == nullptr);
- }
- private:
- const node_type *node;
- };
- /*! @brief Opaque wrapper for types. */
- class meta_type {
- template<auto Member, typename Pred>
- [[nodiscard]] std::decay_t<decltype(std::declval<internal::meta_type_node>().*Member)> lookup(meta_any *const args, const typename internal::meta_type_node::size_type sz, Pred pred) const {
- std::decay_t<decltype(node->*Member)> candidate{};
- size_type extent{sz + 1u};
- bool ambiguous{};
- for(auto *curr = (node->*Member); curr; curr = curr->next) {
- if(pred(curr) && curr->arity == sz) {
- size_type direct{};
- size_type ext{};
- for(size_type next{}; next < sz && next == (direct + ext) && args[next]; ++next) {
- const auto type = args[next].type();
- const auto other = curr->arg(next);
- if(const auto &info = other.info(); info == type.info()) {
- ++direct;
- } else {
- ext += internal::find_by<&node_type::base>(info, type.node)
- || internal::find_by<&node_type::conv>(info, type.node)
- || (type.node->conversion_helper && other.node->conversion_helper);
- }
- }
- if((direct + ext) == sz) {
- if(ext < extent) {
- candidate = curr;
- extent = ext;
- ambiguous = false;
- } else if(ext == extent) {
- ambiguous = true;
- }
- }
- }
- }
- return (candidate && !ambiguous) ? candidate : decltype(candidate){};
- }
- public:
- /*! @brief Node type. */
- using node_type = internal::meta_type_node;
- /*! @brief Node type. */
- using base_node_type = internal::meta_base_node;
- /*! @brief Unsigned integer type. */
- using size_type = typename node_type::size_type;
- /*! @copydoc meta_prop::meta_prop */
- meta_type(const node_type *curr = nullptr) ENTT_NOEXCEPT
- : node{curr} {}
- /**
- * @brief Constructs an instance from a given base node.
- * @param curr The base node with which to construct the instance.
- */
- meta_type(const base_node_type *curr) ENTT_NOEXCEPT
- : node{curr ? curr->type : nullptr} {}
- /**
- * @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 ENTT_NOEXCEPT {
- return *node->info;
- }
- /**
- * @brief Returns the identifier assigned to a type.
- * @return The identifier assigned to the type.
- */
- [[nodiscard]] id_type id() const ENTT_NOEXCEPT {
- return node->id;
- }
- /**
- * @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 ENTT_NOEXCEPT {
- return 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 ENTT_NOEXCEPT {
- return !!(node->traits & internal::meta_traits::is_arithmetic);
- }
- /**
- * @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 ENTT_NOEXCEPT {
- return !!(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 ENTT_NOEXCEPT {
- return !!(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 ENTT_NOEXCEPT {
- return !!(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 ENTT_NOEXCEPT {
- return !!(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 ENTT_NOEXCEPT {
- return node->remove_pointer();
- }
- /**
- * @brief Checks whether a type is a pointer-like type or not.
- * @return True if the underlying type is a pointer-like one, false
- * otherwise.
- */
- [[nodiscard]] bool is_pointer_like() const ENTT_NOEXCEPT {
- return !!(node->traits & internal::meta_traits::is_meta_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 ENTT_NOEXCEPT {
- return !!(node->traits & internal::meta_traits::is_meta_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 ENTT_NOEXCEPT {
- return !!(node->traits & internal::meta_traits::is_meta_associative_container);
- }
- /**
- * @brief Checks whether a type refers to a recognized class template
- * specialization or not.
- * @return True if the type is a recognized class template specialization,
- * false otherwise.
- */
- [[nodiscard]] bool is_template_specialization() const ENTT_NOEXCEPT {
- return (node->templ != nullptr);
- }
- /**
- * @brief Returns the number of template arguments.
- * @return The number of template arguments.
- */
- [[nodiscard]] size_type template_arity() const ENTT_NOEXCEPT {
- return node->templ ? node->templ->arity : size_type{};
- }
- /**
- * @brief Returns a tag for the class template of the underlying type.
- *
- * @sa meta_class_template_tag
- *
- * @return The tag for the class template of the underlying type.
- */
- [[nodiscard]] inline meta_type template_type() const ENTT_NOEXCEPT {
- return node->templ ? node->templ->type : 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]] inline meta_type template_arg(const size_type index) const ENTT_NOEXCEPT {
- return index < template_arity() ? node->templ->arg(index) : meta_type{};
- }
- /**
- * @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, internal::meta_base_node> base() const ENTT_NOEXCEPT {
- return node->base;
- }
- /**
- * @brief Lookup function for registered base meta types.
- * @param id Unique identifier.
- * @return The registered base meta type for the given identifier, if any.
- */
- [[nodiscard]] meta_type base(const id_type id) const {
- return internal::find_by<&node_type::base>(id, node);
- }
- /**
- * @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> data() const ENTT_NOEXCEPT {
- return node->data;
- }
- /**
- * @brief Lookup function for registered meta data.
- *
- * Registered meta data of base classes will also be visited.
- *
- * @param id Unique identifier.
- * @return The registered meta data for the given identifier, if any.
- */
- [[nodiscard]] meta_data data(const id_type id) const {
- return internal::find_by<&node_type::data>(id, node);
- }
- /**
- * @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> func() const ENTT_NOEXCEPT {
- return node->func;
- }
- /**
- * @brief Lookup function for registered meta functions.
- *
- * Registered meta functions of base classes will also be visited.<br/>
- * In case of overloaded functions, the first one with the required
- * identifier will be returned.
- *
- * @param id Unique identifier.
- * @return The registered meta function for the given identifier, if any.
- */
- [[nodiscard]] meta_func func(const id_type id) const {
- return internal::find_by<&node_type::func>(id, node);
- }
- /**
- * @brief Creates an instance of the underlying type, if possible.
- *
- * Parameters are such that a cast or conversion to the required types is
- * possible. Otherwise, an empty and thus invalid wrapper is returned.<br/>
- * If suitable, the implicitly generated default constructor is used.
- *
- * @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 {
- const auto *candidate = lookup<&node_type::ctor>(args, sz, [](const auto *) { return true; });
- return candidate ? candidate->invoke(args) : ((!sz && node->default_constructor) ? node->default_constructor() : meta_any{});
- }
- /**
- * @copybrief construct
- *
- * @sa 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 {
- meta_any arguments[sizeof...(Args) + 1u]{std::forward<Args>(args)...};
- return construct(arguments, sizeof...(Args));
- }
- /**
- * @brief Invokes a function given an identifier, if possible.
- *
- * It must be possible to cast the instance to the parent type of the member
- * function.
- *
- * @sa meta_func::invoke
- *
- * @param id Unique identifier.
- * @param instance An opaque instance of 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.
- */
- meta_any invoke(const id_type id, meta_handle instance, meta_any *const args, const size_type sz) const {
- const auto *candidate = lookup<&node_type::func>(args, sz, [id](const auto *curr) { return curr->id == id; });
- for(auto it = base().begin(), last = base().end(); it != last && !candidate; ++it) {
- candidate = it->lookup<&node_type::func>(args, sz, [id](const auto *curr) { return curr->id == id; });
- }
- return candidate ? candidate->invoke(std::move(instance), args) : meta_any{};
- }
- /**
- * @copybrief invoke
- *
- * @sa invoke
- *
- * @param id Unique identifier.
- * @tparam Args Types of arguments to use to invoke the function.
- * @param instance An opaque instance of the underlying type.
- * @param args Parameters to use to invoke the function.
- * @return A wrapper containing the new instance, if any.
- */
- template<typename... Args>
- meta_any invoke(const id_type id, meta_handle instance, Args &&...args) const {
- meta_any arguments[sizeof...(Args) + 1u]{std::forward<Args>(args)...};
- return invoke(id, std::move(instance), arguments, sizeof...(Args));
- }
- /**
- * @brief Sets the value of a given variable.
- *
- * It must be possible to cast the instance to the parent type of the data
- * member.<br/>
- * The type of the value is such that a cast or conversion to the type of
- * the variable is possible. Otherwise, invoking the setter does nothing.
- *
- * @tparam Type Type of value to assign.
- * @param id Unique identifier.
- * @param instance An opaque instance of the underlying type.
- * @param value Parameter to use to set the underlying variable.
- * @return True in case of success, false otherwise.
- */
- template<typename Type>
- bool set(const id_type id, meta_handle instance, Type &&value) const {
- const auto candidate = data(id);
- return candidate && candidate.set(std::move(instance), std::forward<Type>(value));
- }
- /**
- * @brief Gets the value of a given variable.
- *
- * It must be possible to cast the instance to the parent type of the data
- * member.
- *
- * @param id Unique identifier.
- * @param instance An opaque instance of the underlying type.
- * @return A wrapper containing the value of the underlying variable.
- */
- [[nodiscard]] meta_any get(const id_type id, meta_handle instance) const {
- const auto candidate = data(id);
- return candidate ? candidate.get(std::move(instance)) : meta_any{};
- }
- /**
- * @brief Returns a range to visit registered top-level meta properties.
- * @return An iterable range to visit registered top-level meta properties.
- */
- [[nodiscard]] meta_range<meta_prop> prop() const ENTT_NOEXCEPT {
- return node->prop;
- }
- /**
- * @brief Lookup function for meta properties.
- *
- * Properties of base classes are also visited.
- *
- * @param key The key to use to search for a property.
- * @return The registered meta property for the given key, if any.
- */
- [[nodiscard]] meta_prop prop(meta_any key) const {
- return internal::find_by<&internal::meta_type_node::prop>(key, node);
- }
- /**
- * @brief Returns true if an object is valid, false otherwise.
- * @return True if the object is valid, false otherwise.
- */
- [[nodiscard]] explicit operator bool() const ENTT_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_type &other) const ENTT_NOEXCEPT {
- return (!node && !other.node) || (node && other.node && *node->info == *other.node->info);
- }
- private:
- const node_type *node;
- };
- /**
- * @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_type &lhs, const meta_type &rhs) ENTT_NOEXCEPT {
- return !(lhs == rhs);
- }
- [[nodiscard]] inline meta_type meta_any::type() const ENTT_NOEXCEPT {
- return node;
- }
- template<typename... Args>
- 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(const auto &info = type.info(); node && *node->info == info) {
- return as_ref();
- } else if(node) {
- for(auto *it = node->conv; it; it = it->next) {
- if(*it->type->info == info) {
- return it->conv(*this);
- }
- }
- if(node->conversion_helper && (type.is_arithmetic() || type.is_enum())) {
- // exploits the fact that arithmetic types and enums are also default constructible
- auto other = type.construct();
- ENTT_ASSERT(other.node->conversion_helper, "Conversion helper not found");
- const auto value = node->conversion_helper(nullptr, storage.data());
- other.node->conversion_helper(other.storage.data(), &value);
- return other;
- }
- for(auto *it = node->base; it; it = it->next) {
- const auto as_const = it->cast(as_ref());
- if(auto other = as_const.allow_cast(type); other) {
- return other;
- }
- }
- }
- return {};
- }
- inline bool meta_any::assign(const meta_any &other) {
- auto value = other.allow_cast(node);
- return value && storage.assign(std::move(value.storage));
- }
- inline bool meta_any::assign(meta_any &&other) {
- if(*node->info == *other.node->info) {
- return storage.assign(std::move(other.storage));
- }
- return assign(std::as_const(other));
- }
- [[nodiscard]] inline meta_type meta_data::type() const ENTT_NOEXCEPT {
- return node->type;
- }
- [[nodiscard]] inline meta_type meta_func::ret() const ENTT_NOEXCEPT {
- return node->ret;
- }
- [[nodiscard]] inline meta_type meta_data::arg(const size_type index) const ENTT_NOEXCEPT {
- return index < arity() ? node->arg(index) : meta_type{};
- }
- [[nodiscard]] inline meta_type meta_func::arg(const size_type index) const ENTT_NOEXCEPT {
- return index < arity() ? node->arg(index) : meta_type{};
- }
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- class meta_sequence_container::meta_iterator final {
- friend class meta_sequence_container;
- using deref_fn_type = meta_any(const any &, const std::ptrdiff_t);
- template<typename It>
- static meta_any deref_fn(const any &value, const std::ptrdiff_t pos) {
- return meta_any{std::in_place_type<typename std::iterator_traits<It>::reference>, any_cast<const It &>(value)[pos]};
- }
- public:
- using difference_type = std::ptrdiff_t;
- using value_type = meta_any;
- using pointer = input_iterator_pointer<value_type>;
- using reference = value_type;
- using iterator_category = std::input_iterator_tag;
- meta_iterator() ENTT_NOEXCEPT
- : deref{},
- offset{},
- handle{} {}
- template<typename Type>
- explicit meta_iterator(Type &cont, const difference_type init) ENTT_NOEXCEPT
- : deref{&deref_fn<decltype(cont.begin())>},
- offset{init},
- handle{cont.begin()} {}
- meta_iterator &operator++() ENTT_NOEXCEPT {
- return ++offset, *this;
- }
- meta_iterator operator++(int value) ENTT_NOEXCEPT {
- meta_iterator orig = *this;
- offset += ++value;
- return orig;
- }
- meta_iterator &operator--() ENTT_NOEXCEPT {
- return --offset, *this;
- }
- meta_iterator operator--(int value) ENTT_NOEXCEPT {
- meta_iterator orig = *this;
- offset -= ++value;
- return orig;
- }
- [[nodiscard]] reference operator*() const {
- return deref(handle, offset);
- }
- [[nodiscard]] pointer operator->() const {
- return operator*();
- }
- [[nodiscard]] explicit operator bool() const ENTT_NOEXCEPT {
- return static_cast<bool>(handle);
- }
- [[nodiscard]] bool operator==(const meta_iterator &other) const ENTT_NOEXCEPT {
- return offset == other.offset;
- }
- [[nodiscard]] bool operator!=(const meta_iterator &other) const ENTT_NOEXCEPT {
- return !(*this == other);
- }
- private:
- deref_fn_type *deref;
- difference_type offset;
- any handle;
- };
- class meta_associative_container::meta_iterator final {
- enum class operation : std::uint8_t {
- incr,
- deref
- };
- using vtable_type = void(const operation, const any &, std::pair<meta_any, meta_any> *);
- template<bool KeyOnly, typename It>
- static void basic_vtable(const operation op, const any &value, std::pair<meta_any, meta_any> *other) {
- switch(op) {
- case operation::incr:
- ++any_cast<It &>(const_cast<any &>(value));
- break;
- case operation::deref:
- const auto &it = any_cast<const It &>(value);
- 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);
- }
- break;
- }
- }
- public:
- using difference_type = std::ptrdiff_t;
- using value_type = std::pair<meta_any, meta_any>;
- using pointer = input_iterator_pointer<value_type>;
- using reference = value_type;
- using iterator_category = std::input_iterator_tag;
- meta_iterator() ENTT_NOEXCEPT
- : vtable{},
- handle{} {}
- template<bool KeyOnly, typename It>
- meta_iterator(std::integral_constant<bool, KeyOnly>, It iter) ENTT_NOEXCEPT
- : vtable{&basic_vtable<KeyOnly, It>},
- handle{std::move(iter)} {}
- meta_iterator &operator++() ENTT_NOEXCEPT {
- vtable(operation::incr, handle, nullptr);
- return *this;
- }
- meta_iterator operator++(int) ENTT_NOEXCEPT {
- meta_iterator orig = *this;
- return ++(*this), orig;
- }
- [[nodiscard]] reference operator*() const {
- reference other;
- vtable(operation::deref, handle, &other);
- return other;
- }
- [[nodiscard]] pointer operator->() const {
- return operator*();
- }
- [[nodiscard]] explicit operator bool() const ENTT_NOEXCEPT {
- return static_cast<bool>(handle);
- }
- [[nodiscard]] bool operator==(const meta_iterator &other) const ENTT_NOEXCEPT {
- return handle == other.handle;
- }
- [[nodiscard]] bool operator!=(const meta_iterator &other) const ENTT_NOEXCEPT {
- return !(*this == other);
- }
- private:
- vtable_type *vtable;
- any handle;
- };
- /**
- * Internal details not to be documented.
- * @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 ENTT_NOEXCEPT {
- return value_type_node;
- }
- /**
- * @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 ENTT_NOEXCEPT {
- return size_fn(storage);
- }
- /**
- * @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 resize_fn(storage, sz);
- }
- /**
- * @brief Clears the content of a container.
- * @return True in case of success, false otherwise.
- */
- inline bool meta_sequence_container::clear() {
- return resize_fn(storage, 0u);
- }
- /**
- * @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 iter_fn(storage, 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 iter_fn(storage, 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(iterator it, meta_any value) {
- return insert_fn(storage, it.offset, value);
- }
- /**
- * @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(iterator it) {
- return erase_fn(storage, it.offset);
- }
- /**
- * @brief Returns a reference to the element at a given location of a container
- * (no bounds checking is performed).
- * @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 ENTT_NOEXCEPT {
- return static_cast<bool>(storage);
- }
- /**
- * @brief Returns true if a container is also key-only, false otherwise.
- * @return True if the associative container is also key-only, false otherwise.
- */
- [[nodiscard]] inline bool meta_associative_container::key_only() const ENTT_NOEXCEPT {
- return key_only_container;
- }
- /**
- * @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 ENTT_NOEXCEPT {
- return key_type_node;
- }
- /**
- * @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 ENTT_NOEXCEPT {
- return mapped_type_node;
- }
- /*! @copydoc meta_sequence_container::value_type */
- [[nodiscard]] inline meta_type meta_associative_container::value_type() const ENTT_NOEXCEPT {
- return value_type_node;
- }
- /*! @copydoc meta_sequence_container::size */
- [[nodiscard]] inline meta_associative_container::size_type meta_associative_container::size() const ENTT_NOEXCEPT {
- return size_fn(storage);
- }
- /*! @copydoc meta_sequence_container::clear */
- inline bool meta_associative_container::clear() {
- return clear_fn(storage);
- }
- /*! @copydoc meta_sequence_container::begin */
- [[nodiscard]] inline meta_associative_container::iterator meta_associative_container::begin() {
- return iter_fn(storage, false);
- }
- /*! @copydoc meta_sequence_container::end */
- [[nodiscard]] inline meta_associative_container::iterator meta_associative_container::end() {
- return iter_fn(storage, true);
- }
- /**
- * @brief Inserts an element (a key/value pair) into a container.
- * @param key The key of the element to insert.
- * @param value The value of the element to insert.
- * @return A bool denoting whether the insertion took place.
- */
- inline bool meta_associative_container::insert(meta_any key, meta_any value = {}) {
- return insert_fn(storage, key, value);
- }
- /**
- * @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 bool meta_associative_container::erase(meta_any key) {
- return erase_fn(storage, key);
- }
- /**
- * @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 find_fn(storage, key);
- }
- /**
- * @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 ENTT_NOEXCEPT {
- return static_cast<bool>(storage);
- }
- } // namespace entt
- #endif
- // #include "meta/node.hpp"
- #ifndef ENTT_META_NODE_HPP
- #define ENTT_META_NODE_HPP
- #include <cstddef>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- // #include "../core/attribute.h"
- // #include "../core/enum.hpp"
- // #include "../core/fwd.hpp"
- // #include "../core/type_info.hpp"
- // #include "../core/type_traits.hpp"
- // #include "type_traits.hpp"
- namespace entt {
- class meta_any;
- class meta_type;
- struct meta_handle;
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- namespace internal {
- enum class meta_traits : std::uint32_t {
- is_none = 0x0000,
- is_const = 0x0001,
- is_static = 0x0002,
- is_arithmetic = 0x0004,
- is_array = 0x0008,
- is_enum = 0x0010,
- is_class = 0x0020,
- is_pointer = 0x0040,
- is_meta_pointer_like = 0x0080,
- is_meta_sequence_container = 0x0100,
- is_meta_associative_container = 0x0200,
- _entt_enum_as_bitmask
- };
- struct meta_type_node;
- struct meta_prop_node {
- meta_prop_node *next;
- const meta_any &id;
- meta_any &value;
- };
- struct meta_base_node {
- meta_base_node *next;
- meta_type_node *const type;
- meta_any (*const cast)(meta_any) ENTT_NOEXCEPT;
- };
- struct meta_conv_node {
- meta_conv_node *next;
- meta_type_node *const type;
- meta_any (*const conv)(const meta_any &);
- };
- struct meta_ctor_node {
- using size_type = std::size_t;
- meta_ctor_node *next;
- const size_type arity;
- meta_type (*const arg)(const size_type) ENTT_NOEXCEPT;
- meta_any (*const invoke)(meta_any *const);
- };
- struct meta_data_node {
- using size_type = std::size_t;
- id_type id;
- const meta_traits traits;
- meta_data_node *next;
- meta_prop_node *prop;
- const size_type arity;
- meta_type_node *const type;
- meta_type (*const arg)(const size_type) ENTT_NOEXCEPT;
- bool (*const set)(meta_handle, meta_any);
- meta_any (*const get)(meta_handle);
- };
- struct meta_func_node {
- using size_type = std::size_t;
- id_type id;
- const meta_traits traits;
- meta_func_node *next;
- meta_prop_node *prop;
- const size_type arity;
- meta_type_node *const ret;
- meta_type (*const arg)(const size_type) ENTT_NOEXCEPT;
- meta_any (*const invoke)(meta_handle, meta_any *const);
- };
- struct meta_template_node {
- using size_type = std::size_t;
- const size_type arity;
- meta_type_node *const type;
- meta_type_node *(*const arg)(const size_type)ENTT_NOEXCEPT;
- };
- struct meta_type_node {
- using size_type = std::size_t;
- const type_info *info;
- id_type id;
- const meta_traits traits;
- meta_type_node *next;
- meta_prop_node *prop;
- const size_type size_of;
- meta_type_node *(*const remove_pointer)() ENTT_NOEXCEPT;
- meta_any (*const default_constructor)();
- double (*const conversion_helper)(void *, const void *);
- const meta_template_node *const templ;
- meta_ctor_node *ctor{nullptr};
- meta_base_node *base{nullptr};
- meta_conv_node *conv{nullptr};
- meta_data_node *data{nullptr};
- meta_func_node *func{nullptr};
- void (*dtor)(void *){nullptr};
- };
- template<typename... Args>
- meta_type_node *meta_arg_node(type_list<Args...>, const std::size_t index) ENTT_NOEXCEPT;
- template<typename Type>
- class ENTT_API meta_node {
- static_assert(std::is_same_v<Type, std::remove_cv_t<std::remove_reference_t<Type>>>, "Invalid type");
- [[nodiscard]] static auto *meta_default_constructor() ENTT_NOEXCEPT {
- if constexpr(std::is_default_constructible_v<Type>) {
- return +[]() { return meta_any{std::in_place_type<Type>}; };
- } else {
- return static_cast<std::decay_t<decltype(meta_type_node::default_constructor)>>(nullptr);
- }
- }
- [[nodiscard]] static auto *meta_conversion_helper() ENTT_NOEXCEPT {
- if constexpr(std::is_arithmetic_v<Type>) {
- return +[](void *bin, const void *value) {
- return bin ? static_cast<double>(*static_cast<Type *>(bin) = static_cast<Type>(*static_cast<const double *>(value))) : static_cast<double>(*static_cast<const Type *>(value));
- };
- } else if constexpr(std::is_enum_v<Type>) {
- return +[](void *bin, const void *value) {
- return bin ? static_cast<double>(*static_cast<Type *>(bin) = static_cast<Type>(static_cast<std::underlying_type_t<Type>>(*static_cast<const double *>(value)))) : static_cast<double>(*static_cast<const Type *>(value));
- };
- } else {
- return static_cast<std::decay_t<decltype(meta_type_node::conversion_helper)>>(nullptr);
- }
- }
- [[nodiscard]] static meta_template_node *meta_template_info() ENTT_NOEXCEPT {
- if constexpr(is_complete_v<meta_template_traits<Type>>) {
- static meta_template_node node{
- meta_template_traits<Type>::args_type::size,
- meta_node<typename meta_template_traits<Type>::class_type>::resolve(),
- [](const std::size_t index) ENTT_NOEXCEPT { return meta_arg_node(typename meta_template_traits<Type>::args_type{}, index); }
- // tricks clang-format
- };
- return &node;
- } else {
- return nullptr;
- }
- }
- public:
- [[nodiscard]] static meta_type_node *resolve() ENTT_NOEXCEPT {
- static meta_type_node node{
- &type_id<Type>(),
- {},
- internal::meta_traits::is_none
- | (std::is_arithmetic_v<Type> ? internal::meta_traits::is_arithmetic : internal::meta_traits::is_none)
- | (std::is_array_v<Type> ? internal::meta_traits::is_array : internal::meta_traits::is_none)
- | (std::is_enum_v<Type> ? internal::meta_traits::is_enum : internal::meta_traits::is_none)
- | (std::is_class_v<Type> ? internal::meta_traits::is_class : internal::meta_traits::is_none)
- | (std::is_pointer_v<Type> ? internal::meta_traits::is_pointer : internal::meta_traits::is_none)
- | (is_meta_pointer_like_v<Type> ? internal::meta_traits::is_meta_pointer_like : internal::meta_traits::is_none)
- | (is_complete_v<meta_sequence_container_traits<Type>> ? internal::meta_traits::is_meta_sequence_container : internal::meta_traits::is_none)
- | (is_complete_v<meta_associative_container_traits<Type>> ? internal::meta_traits::is_meta_associative_container : internal::meta_traits::is_none),
- nullptr,
- nullptr,
- size_of_v<Type>,
- &meta_node<std::remove_cv_t<std::remove_reference_t<std::remove_pointer_t<Type>>>>::resolve,
- meta_default_constructor(),
- meta_conversion_helper(),
- meta_template_info()
- // tricks clang-format
- };
- return &node;
- }
- };
- template<typename... Args>
- [[nodiscard]] meta_type_node *meta_arg_node(type_list<Args...>, const std::size_t index) ENTT_NOEXCEPT {
- meta_type_node *args[sizeof...(Args) + 1u]{nullptr, internal::meta_node<std::remove_cv_t<std::remove_reference_t<Args>>>::resolve()...};
- return args[index + 1u];
- }
- template<auto Member, typename Type>
- [[nodiscard]] static std::decay_t<decltype(std::declval<internal::meta_type_node>().*Member)> find_by(const Type &info_or_id, const internal::meta_type_node *node) ENTT_NOEXCEPT {
- for(auto *curr = node->*Member; curr; curr = curr->next) {
- if constexpr(std::is_same_v<Type, type_info>) {
- if(*curr->type->info == info_or_id) {
- return curr;
- }
- } else if constexpr(std::is_same_v<decltype(curr), meta_base_node *>) {
- if(curr->type->id == info_or_id) {
- return curr;
- }
- } else {
- if(curr->id == info_or_id) {
- return curr;
- }
- }
- }
- for(auto *curr = node->base; curr; curr = curr->next) {
- if(auto *ret = find_by<Member>(info_or_id, curr->type); ret) {
- return ret;
- }
- }
- return nullptr;
- }
- } // namespace internal
- /**
- * Internal details not to be documented.
- * @endcond
- */
- } // namespace entt
- #endif
- // #include "meta/pointer.hpp"
- #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>
- 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 {};
- } // namespace entt
- #endif
- // #include "meta/policy.hpp"
- #ifndef ENTT_META_POLICY_HPP
- #define ENTT_META_POLICY_HPP
- #include <type_traits>
- namespace entt {
- /*! @brief Empty class type used to request the _as ref_ policy. */
- struct as_ref_t {
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- template<typename Type>
- static constexpr bool value = std::is_reference_v<Type> && !std::is_const_v<std::remove_reference_t<Type>>;
- /**
- * Internal details not to be documented.
- * @endcond
- */
- };
- /*! @brief Empty class type used to request the _as cref_ policy. */
- struct as_cref_t {
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- template<typename Type>
- static constexpr bool value = std::is_reference_v<Type>;
- /**
- * Internal details not to be documented.
- * @endcond
- */
- };
- /*! @brief Empty class type used to request the _as-is_ policy. */
- struct as_is_t {
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- template<typename>
- static constexpr bool value = true;
- /**
- * Internal details not to be documented.
- * @endcond
- */
- };
- /*! @brief Empty class type used to request the _as void_ policy. */
- struct as_void_t {
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- template<typename>
- static constexpr bool value = true;
- /**
- * Internal details not to be documented.
- * @endcond
- */
- };
- } // namespace entt
- #endif
- // #include "meta/range.hpp"
- #ifndef ENTT_META_RANGE_HPP
- #define ENTT_META_RANGE_HPP
- #include <cstddef>
- #include <iterator>
- // #include "../core/iterator.hpp"
- namespace entt {
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- namespace internal {
- template<typename Type, typename Node>
- struct meta_range_iterator final {
- using difference_type = std::ptrdiff_t;
- using value_type = Type;
- using pointer = input_iterator_pointer<value_type>;
- using reference = value_type;
- using iterator_category = std::input_iterator_tag;
- using node_type = Node;
- meta_range_iterator() ENTT_NOEXCEPT
- : it{} {}
- meta_range_iterator(node_type *head) ENTT_NOEXCEPT
- : it{head} {}
- meta_range_iterator &operator++() ENTT_NOEXCEPT {
- return (it = it->next), *this;
- }
- meta_range_iterator operator++(int) ENTT_NOEXCEPT {
- meta_range_iterator orig = *this;
- return ++(*this), orig;
- }
- [[nodiscard]] reference operator*() const ENTT_NOEXCEPT {
- return it;
- }
- [[nodiscard]] pointer operator->() const ENTT_NOEXCEPT {
- return operator*();
- }
- [[nodiscard]] bool operator==(const meta_range_iterator &other) const ENTT_NOEXCEPT {
- return it == other.it;
- }
- [[nodiscard]] bool operator!=(const meta_range_iterator &other) const ENTT_NOEXCEPT {
- return !(*this == other);
- }
- private:
- node_type *it;
- };
- } // namespace internal
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /**
- * @brief Iterable range to use to iterate all types of meta objects.
- * @tparam Type Type of meta objects returned.
- * @tparam Node Type of meta nodes iterated.
- */
- template<typename Type, typename Node = typename Type::node_type>
- struct meta_range final {
- /*! @brief Node type. */
- using node_type = Node;
- /*! @brief Input iterator type. */
- using iterator = internal::meta_range_iterator<Type, Node>;
- /*! @brief Constant input iterator type. */
- using const_iterator = iterator;
- /*! @brief Default constructor. */
- meta_range() ENTT_NOEXCEPT = default;
- /**
- * @brief Constructs a meta range from a given node.
- * @param head The underlying node with which to construct the range.
- */
- meta_range(node_type *head) ENTT_NOEXCEPT
- : node{head} {}
- /**
- * @brief Returns an iterator to the beginning.
- * @return An iterator to the first meta object of the range.
- */
- [[nodiscard]] const_iterator cbegin() const ENTT_NOEXCEPT {
- return iterator{node};
- }
- /*! @copydoc cbegin */
- [[nodiscard]] iterator begin() const ENTT_NOEXCEPT {
- return cbegin();
- }
- /**
- * @brief Returns an iterator to the end.
- * @return An iterator to the element following the last meta object of the
- * range.
- */
- [[nodiscard]] const_iterator cend() const ENTT_NOEXCEPT {
- return iterator{};
- }
- /*! @copydoc cend */
- [[nodiscard]] iterator end() const ENTT_NOEXCEPT {
- return cend();
- }
- private:
- node_type *node{nullptr};
- };
- } // namespace entt
- #endif
- // #include "meta/resolve.hpp"
- #ifndef ENTT_META_RESOLVE_HPP
- #define ENTT_META_RESOLVE_HPP
- #include <algorithm>
- // #include "../core/type_info.hpp"
- // #include "ctx.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.
- * @return The meta type associated with the given type, if any.
- */
- template<typename Type>
- [[nodiscard]] meta_type resolve() ENTT_NOEXCEPT {
- return internal::meta_node<std::remove_cv_t<std::remove_reference_t<Type>>>::resolve();
- }
- /**
- * @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> resolve() ENTT_NOEXCEPT {
- return *internal::meta_context::global();
- }
- /**
- * @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) ENTT_NOEXCEPT {
- for(auto &&curr: resolve()) {
- if(curr.id() == id) {
- return curr;
- }
- }
- return {};
- }
- /**
- * @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) ENTT_NOEXCEPT {
- for(auto &&curr: resolve()) {
- if(curr.info() == info) {
- return curr;
- }
- }
- return {};
- }
- } // namespace entt
- #endif
- // #include "meta/template.hpp"
- #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.
- * @tparam Type Potentially pointer-like type.
- */
- template<typename>
- 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 "../config/config.h"
- // #include "../core/type_traits.hpp"
- // #include "meta.hpp"
- // #include "node.hpp"
- // #include "policy.hpp"
- namespace entt {
- /*! @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> {
- /*! @brief Meta function return type. */
- using return_type = Ret;
- /*! @brief Meta function arguments. */
- using args_type = std::conditional_t<std::is_base_of_v<Class, Type>, type_list<Args...>, type_list<const Class &, Args...>>;
- /*! @brief True if the meta function is const, false otherwise. */
- static constexpr auto is_const = true;
- /*! @brief True if the meta function is static, false otherwise. */
- static constexpr auto is_static = !std::is_base_of_v<Class, Type>;
- };
- /**
- * @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...)> {
- /*! @brief Meta function return type. */
- using return_type = Ret;
- /*! @brief Meta function arguments. */
- using args_type = std::conditional_t<std::is_base_of_v<Class, Type>, type_list<Args...>, type_list<Class &, Args...>>;
- /*! @brief True if the meta function is const, false otherwise. */
- static constexpr auto is_const = false;
- /*! @brief True if the meta function is static, false otherwise. */
- static constexpr auto is_static = !std::is_base_of_v<Class, Type>;
- };
- /**
- * @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::*> {
- /*! @brief Meta data return type. */
- using return_type = Ret &;
- /*! @brief Meta data arguments. */
- using args_type = std::conditional_t<std::is_base_of_v<Class, Type>, type_list<>, type_list<Class &>>;
- /*! @brief True if the meta data is const, false otherwise. */
- static constexpr auto is_const = false;
- /*! @brief True if the meta data is static, false otherwise. */
- static constexpr auto is_static = !std::is_base_of_v<Class, Type>;
- };
- /**
- * @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...)> {
- /*! @brief Meta function return type. */
- using return_type = Ret;
- /*! @brief Meta function arguments. */
- using args_type = std::conditional_t<std::is_base_of_v<std::remove_cv_t<std::remove_reference_t<MaybeType>>, Type>, type_list<Args...>, type_list<MaybeType, Args...>>;
- /*! @brief True if the meta function is const, false otherwise. */
- static constexpr auto is_const = std::is_base_of_v<std::remove_cv_t<std::remove_reference_t<MaybeType>>, Type> && std::is_const_v<std::remove_reference_t<MaybeType>>;
- /*! @brief True if the meta function is static, false otherwise. */
- static constexpr auto is_static = !std::is_base_of_v<std::remove_cv_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 (*)()> {
- /*! @brief Meta function return type. */
- using return_type = Ret;
- /*! @brief Meta function arguments. */
- using args_type = type_list<>;
- /*! @brief True if the meta function is const, false otherwise. */
- static constexpr auto is_const = false;
- /*! @brief True if the meta function is static, false otherwise. */
- static constexpr auto is_static = true;
- };
- /**
- * @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>
- 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.
- * @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_is_t, typename Type>
- meta_any meta_dispatch([[maybe_unused]] Type &&value) {
- if constexpr(std::is_same_v<Policy, as_void_t>) {
- return meta_any{std::in_place_type<void>};
- } else if constexpr(std::is_same_v<Policy, as_ref_t>) {
- return meta_any{std::in_place_type<Type>, std::forward<Type>(value)};
- } else if constexpr(std::is_same_v<Policy, as_cref_t>) {
- static_assert(std::is_lvalue_reference_v<Type>, "Invalid type");
- return meta_any{std::in_place_type<const std::remove_reference_t<Type> &>, std::as_const(value)};
- } else {
- static_assert(std::is_same_v<Policy, as_is_t>, "Policy not supported");
- return meta_any{std::forward<Type>(value)};
- }
- }
- /**
- * @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.
- * @return The meta type of the i-th element of the list of arguments.
- */
- template<typename Type>
- [[nodiscard]] static meta_type meta_arg(const std::size_t index) ENTT_NOEXCEPT {
- return internal::meta_arg_node(Type{}, 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_same_v<decltype(Data), Type> && !std::is_same_v<decltype(Data), std::nullptr_t>) {
- 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 {
- 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_is_t>
- [[nodiscard]] meta_any meta_getter([[maybe_unused]] 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_cv_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>(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>(std::invoke(Data, *fallback));
- }
- }
- }
- return meta_any{};
- } else if constexpr(std::is_pointer_v<decltype(Data)>) {
- if constexpr(std::is_array_v<std::remove_pointer_t<decltype(Data)>>) {
- return meta_any{};
- } else {
- return meta_dispatch<Policy>(*Data);
- }
- } else {
- return meta_dispatch<Policy>(Data);
- }
- }
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- namespace internal {
- template<typename Type, typename Policy, typename Candidate, typename... Args>
- [[nodiscard]] meta_any meta_invoke_with_args(Candidate &&candidate, Args &&...args) {
- if constexpr(std::is_same_v<std::invoke_result_t<decltype(candidate), Args...>, void>) {
- std::invoke(candidate, args...);
- return meta_any{std::in_place_type<void>};
- } else {
- return meta_dispatch<Policy>(std::invoke(candidate, args...));
- }
- }
- template<typename Type, typename Policy, typename Candidate, std::size_t... Index>
- [[nodiscard]] meta_any meta_invoke([[maybe_unused]] meta_handle instance, Candidate &&candidate, [[maybe_unused]] meta_any *args, std::index_sequence<Index...>) {
- using descriptor = meta_function_helper_t<Type, std::remove_reference_t<Candidate>>;
- 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<Type, Policy>(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<Type, Policy>(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<Type, Policy>(std::forward<Candidate>(candidate), (args + Index)->cast<type_list_element_t<Index, typename descriptor::args_type>>()...);
- }
- }
- return meta_any{};
- }
- template<typename Type, typename... Args, std::size_t... Index>
- [[nodiscard]] meta_any meta_construct(meta_any *const args, std::index_sequence<Index...>) {
- if(((args + Index)->allow_cast<Args>() && ...)) {
- return meta_any{std::in_place_type<Type>, (args + Index)->cast<Args>()...};
- }
- return meta_any{};
- }
- } // namespace internal
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /**
- * @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_is_t, typename Candidate>
- [[nodiscard]] meta_any meta_invoke([[maybe_unused]] meta_handle instance, Candidate &&candidate, [[maybe_unused]] meta_any *const args) {
- return internal::meta_invoke<Type, Policy>(std::move(instance), 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_is_t>
- [[nodiscard]] meta_any meta_invoke(meta_handle instance, meta_any *const args) {
- return internal::meta_invoke<Type, Policy>(std::move(instance), 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.
- * @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 internal::meta_construct<Type, Args...>(args, std::index_sequence_for<Args...>{});
- }
- /**
- * @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 args Parameters to use to _invoke_ the object.
- * @param candidate The actual object to _invoke_.
- * @return A meta any containing the returned value, if any.
- */
- template<typename Type, typename Policy = as_is_t, typename Candidate>
- [[nodiscard]] meta_any meta_construct(Candidate &&candidate, meta_any *const args) {
- if constexpr(meta_function_helper_t<Type, Candidate>::is_static) {
- return internal::meta_invoke<Type, Policy>({}, std::forward<Candidate>(candidate), args, std::make_index_sequence<meta_function_helper_t<Type, std::remove_reference_t<Candidate>>::args_type::size>{});
- } else {
- 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 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_is_t>
- [[nodiscard]] meta_any meta_construct(meta_any *const args) {
- return meta_construct<Type, Policy>(Candidate, args);
- }
- } // namespace entt
- #endif
- // #include "platform/android-ndk-r17.hpp"
- #ifndef ENTT_PLATFORM_ANDROID_NDK_R17_HPP
- #define ENTT_PLATFORM_ANDROID_NDK_R17_HPP
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- #ifdef __ANDROID__
- # include <android/ndk-version.h>
- # if __NDK_MAJOR__ == 17
- # include <functional>
- # include <type_traits>
- # include <utility>
- namespace std {
- namespace internal {
- template<typename Func, typename... Args>
- constexpr auto is_invocable(int) -> decltype(std::invoke(std::declval<Func>(), std::declval<Args>()...), std::true_type{});
- template<typename, typename...>
- constexpr std::false_type is_invocable(...);
- template<typename Ret, typename Func, typename... Args>
- constexpr auto is_invocable_r(int)
- -> std::enable_if_t<decltype(std::is_convertible_v<decltype(std::invoke(std::declval<Func>(), std::declval<Args>()...)), Ret>, std::true_type>;
- template<typename, typename, typename...>
- constexpr std::false_type is_invocable_r(...);
- } // namespace internal
- template<typename Func, typename... Args>
- struct is_invocable: decltype(internal::is_invocable<Func, Args...>(0)) {};
- template<typename Func, typename... Argsv>
- inline constexpr bool is_invocable_v = std::is_invocable<Func, Args...>::value;
- template<typename Ret, typename Func, typename... Args>
- struct is_invocable_r: decltype(internal::is_invocable_r<Ret, Func, Args...>(0)) {};
- template<typename Ret, typename Func, typename... Args>
- inline constexpr bool is_invocable_r_v = std::is_invocable_r<Ret, Func, Args...>::value;
- template<typename Func, typename... Args>
- struct invoke_result {
- using type = decltype(std::invoke(std::declval<Func>(), std::declval<Args>()...));
- };
- template<typename Func, typename... Args>
- using invoke_result_t = typename std::invoke_result<Func, Args...>::type;
- } // namespace std
- # endif
- #endif
- /**
- * Internal details not to be documented.
- * @endcond
- */
- #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 "../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
- #define ENTT_STR(arg) #arg
- #define ENTT_XSTR(arg) ENTT_STR(arg)
- #endif
- #define ENTT_VERSION_MAJOR 3
- #define ENTT_VERSION_MINOR 10
- #define ENTT_VERSION_PATCH 3
- #define ENTT_VERSION \
- ENTT_XSTR(ENTT_VERSION_MAJOR) \
- "." ENTT_XSTR(ENTT_VERSION_MINOR) "." ENTT_XSTR(ENTT_VERSION_PATCH)
- #endif
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #ifndef ENTT_NOEXCEPT
- # define ENTT_NOEXCEPT noexcept
- # define ENTT_NOEXCEPT_IF(expr) noexcept(expr)
- # else
- # define ENTT_NOEXCEPT_IF(...)
- #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
- #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(...) (void(0))
- #elif !defined ENTT_ASSERT
- # include <cassert>
- # define ENTT_ASSERT(condition, ...) assert(condition)
- #endif
- #ifdef ENTT_NO_ETO
- # define ENTT_IGNORE_IF_EMPTY false
- #else
- # define ENTT_IGNORE_IF_EMPTY true
- #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
- #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
- #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
- #define ENTT_STR(arg) #arg
- #define ENTT_XSTR(arg) ENTT_STR(arg)
- #endif
- #define ENTT_VERSION_MAJOR 3
- #define ENTT_VERSION_MINOR 10
- #define ENTT_VERSION_PATCH 3
- #define ENTT_VERSION \
- ENTT_XSTR(ENTT_VERSION_MAJOR) \
- "." ENTT_XSTR(ENTT_VERSION_MINOR) "." ENTT_XSTR(ENTT_VERSION_PATCH)
- #endif
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #ifndef ENTT_NOEXCEPT
- # define ENTT_NOEXCEPT noexcept
- # define ENTT_NOEXCEPT_IF(expr) noexcept(expr)
- # else
- # define ENTT_NOEXCEPT_IF(...)
- #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
- #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(...) (void(0))
- #elif !defined ENTT_ASSERT
- # include <cassert>
- # define ENTT_ASSERT(condition, ...) assert(condition)
- #endif
- #ifdef ENTT_NO_ETO
- # define ENTT_IGNORE_IF_EMPTY false
- #else
- # define ENTT_IGNORE_IF_EMPTY true
- #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
- #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
- #endif
- // #include "../core/utility.hpp"
- #ifndef ENTT_CORE_UTILITY_HPP
- #define ENTT_CORE_UTILITY_HPP
- #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
- #define ENTT_STR(arg) #arg
- #define ENTT_XSTR(arg) ENTT_STR(arg)
- #endif
- #define ENTT_VERSION_MAJOR 3
- #define ENTT_VERSION_MINOR 10
- #define ENTT_VERSION_PATCH 3
- #define ENTT_VERSION \
- ENTT_XSTR(ENTT_VERSION_MAJOR) \
- "." ENTT_XSTR(ENTT_VERSION_MINOR) "." ENTT_XSTR(ENTT_VERSION_PATCH)
- #endif
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #ifndef ENTT_NOEXCEPT
- # define ENTT_NOEXCEPT noexcept
- # define ENTT_NOEXCEPT_IF(expr) noexcept(expr)
- # else
- # define ENTT_NOEXCEPT_IF(...)
- #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
- #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(...) (void(0))
- #elif !defined ENTT_ASSERT
- # include <cassert>
- # define ENTT_ASSERT(condition, ...) assert(condition)
- #endif
- #ifdef ENTT_NO_ETO
- # define ENTT_IGNORE_IF_EMPTY false
- #else
- # define ENTT_IGNORE_IF_EMPTY true
- #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
- #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
- #endif
- 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<class Type>
- [[nodiscard]] constexpr Type &&operator()(Type &&value) const ENTT_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) ENTT_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) ENTT_NOEXCEPT {
- return func;
- }
- /**
- * @brief Helper type for visitors.
- * @tparam Func Types of function objects.
- */
- template<class... Func>
- struct overloaded: Func... {
- using Func::operator()...;
- };
- /**
- * @brief Deduction guide.
- * @tparam Func Types of function objects.
- */
- template<class... Func>
- overloaded(Func...) -> overloaded<Func...>;
- /**
- * @brief Basic implementation of a y-combinator.
- * @tparam Func Type of a potentially recursive function.
- */
- template<class Func>
- struct y_combinator {
- /**
- * @brief Constructs a y-combinator from a given function.
- * @param recursive A potentially recursive function.
- */
- y_combinator(Func recursive)
- : 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<class... Args>
- decltype(auto) operator()(Args &&...args) const {
- return func(*this, std::forward<Args>(args)...);
- }
- /*! @copydoc operator()() */
- template<class... Args>
- decltype(auto) operator()(Args &&...args) {
- return func(*this, std::forward<Args>(args)...);
- }
- private:
- Func func;
- };
- } // namespace entt
- #endif
- // #include "fwd.hpp"
- #ifndef ENTT_CORE_FWD_HPP
- #define ENTT_CORE_FWD_HPP
- #include <cstdint>
- #include <type_traits>
- // #include "../config/config.h"
- namespace entt {
- template<std::size_t Len = sizeof(double[2]), std::size_t = alignof(typename std::aligned_storage_t<Len + !Len>)>
- 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<>;
- } // 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 "../core/attribute.h"
- #ifndef ENTT_CORE_ATTRIBUTE_H
- #define ENTT_CORE_ATTRIBUTE_H
- #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
- #endif
- // #include "fwd.hpp"
- // #include "hashed_string.hpp"
- #ifndef ENTT_CORE_HASHED_STRING_HPP
- #define ENTT_CORE_HASHED_STRING_HPP
- #include <cstddef>
- #include <cstdint>
- // #include "../config/config.h"
- // #include "fwd.hpp"
- namespace entt {
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- namespace internal {
- template<typename>
- struct fnv1a_traits;
- template<>
- struct fnv1a_traits<std::uint32_t> {
- using type = std::uint32_t;
- static constexpr std::uint32_t offset = 2166136261;
- static constexpr std::uint32_t prime = 16777619;
- };
- template<>
- struct fnv1a_traits<std::uint64_t> {
- using type = std::uint64_t;
- static constexpr std::uint64_t offset = 14695981039346656037ull;
- static constexpr std::uint64_t 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;
- size_type length;
- hash_type hash;
- };
- } // namespace internal
- /**
- * Internal details not to be documented.
- * @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 hs_traits = internal::fnv1a_traits<id_type>;
- struct const_wrapper {
- // non-explicit constructor on purpose
- constexpr const_wrapper(const Char *str) ENTT_NOEXCEPT: repr{str} {}
- const Char *repr;
- };
- // Fowler–Noll–Vo hash function v. 1a - the good
- [[nodiscard]] static constexpr auto helper(const Char *str) ENTT_NOEXCEPT {
- base_type base{str, 0u, hs_traits::offset};
- for(; str[base.length]; ++base.length) {
- base.hash = (base.hash ^ static_cast<hs_traits::type>(str[base.length])) * hs_traits::prime;
- }
- return base;
- }
- // Fowler–Noll–Vo hash function v. 1a - the good
- [[nodiscard]] static constexpr auto helper(const Char *str, const std::size_t len) ENTT_NOEXCEPT {
- base_type base{str, len, hs_traits::offset};
- for(size_type pos{}; pos < len; ++pos) {
- base.hash = (base.hash ^ static_cast<hs_traits::type>(str[pos])) * hs_traits::prime;
- }
- return base;
- }
- 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) ENTT_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>
- [[nodiscard]] static constexpr hash_type value(const value_type (&str)[N]) ENTT_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) ENTT_NOEXCEPT {
- return basic_hashed_string{wrapper};
- }
- /*! @brief Constructs an empty hashed string. */
- constexpr basic_hashed_string() ENTT_NOEXCEPT
- : base_type{} {}
- /**
- * @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) ENTT_NOEXCEPT
- : base_type{helper(str, len)} {}
- /**
- * @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>
- constexpr basic_hashed_string(const value_type (&str)[N]) ENTT_NOEXCEPT
- : base_type{helper(str)} {}
- /**
- * @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) ENTT_NOEXCEPT
- : base_type{helper(wrapper.repr)} {}
- /**
- * @brief Returns the size a hashed string.
- * @return The size of the hashed string.
- */
- [[nodiscard]] constexpr size_type size() const ENTT_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 ENTT_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 ENTT_NOEXCEPT {
- return base_type::hash;
- }
- /*! @copydoc data */
- [[nodiscard]] constexpr operator const value_type *() const ENTT_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 ENTT_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, const 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>
- 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) ENTT_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) ENTT_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) ENTT_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) ENTT_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) ENTT_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) ENTT_NOEXCEPT {
- return !(lhs < rhs);
- }
- /*! @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>;
- inline namespace literals {
- /**
- * @brief User defined literal for hashed strings.
- * @param str The literal without its suffix.
- * @return A properly initialized hashed string.
- */
- [[nodiscard]] constexpr hashed_string operator"" _hs(const char *str, std::size_t) ENTT_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]] constexpr hashed_wstring operator"" _hws(const wchar_t *str, std::size_t) ENTT_NOEXCEPT {
- return hashed_wstring{str};
- }
- } // namespace literals
- } // namespace entt
- #endif
- namespace entt {
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- namespace internal {
- struct ENTT_API type_index final {
- [[nodiscard]] static id_type next() ENTT_NOEXCEPT {
- static ENTT_MAYBE_ATOMIC(id_type) value{};
- return value++;
- }
- };
- template<typename Type>
- [[nodiscard]] constexpr auto stripped_type_name() ENTT_NOEXCEPT {
- #if defined ENTT_PRETTY_FUNCTION
- std::string_view pretty_function{ENTT_PRETTY_FUNCTION};
- auto first = pretty_function.find_first_not_of(' ', pretty_function.find_first_of(ENTT_PRETTY_FUNCTION_PREFIX) + 1);
- auto value = pretty_function.substr(first, pretty_function.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]] static constexpr std::string_view type_name(int) ENTT_NOEXCEPT {
- constexpr auto value = stripped_type_name<Type>();
- return value;
- }
- template<typename Type>
- [[nodiscard]] static std::string_view type_name(char) ENTT_NOEXCEPT {
- static const auto value = stripped_type_name<Type>();
- return value;
- }
- template<typename Type, auto = stripped_type_name<Type>().find_first_of('.')>
- [[nodiscard]] static constexpr id_type type_hash(int) ENTT_NOEXCEPT {
- constexpr auto stripped = stripped_type_name<Type>();
- constexpr auto value = hashed_string::value(stripped.data(), stripped.size());
- return value;
- }
- template<typename Type>
- [[nodiscard]] static id_type type_hash(char) ENTT_NOEXCEPT {
- static const auto value = [](const auto stripped) {
- return hashed_string::value(stripped.data(), stripped.size());
- }(stripped_type_name<Type>());
- return value;
- }
- } // namespace internal
- /**
- * Internal details not to be documented.
- * @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() ENTT_NOEXCEPT {
- static const id_type value = internal::type_index::next();
- return value;
- }
- /*! @copydoc value */
- [[nodiscard]] constexpr operator id_type() const ENTT_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() ENTT_NOEXCEPT {
- return internal::type_hash<Type>(0);
- #else
- [[nodiscard]] static constexpr id_type value() ENTT_NOEXCEPT {
- return type_index<Type>::value();
- #endif
- }
- /*! @copydoc value */
- [[nodiscard]] constexpr operator id_type() const ENTT_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() ENTT_NOEXCEPT {
- return internal::type_name<Type>(0);
- }
- /*! @copydoc value */
- [[nodiscard]] constexpr operator std::string_view() const ENTT_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>
- constexpr type_info(std::in_place_type_t<Type>) ENTT_NOEXCEPT
- : seq{type_index<std::remove_cv_t<std::remove_reference_t<Type>>>::value()},
- identifier{type_hash<std::remove_cv_t<std::remove_reference_t<Type>>>::value()},
- alias{type_name<std::remove_cv_t<std::remove_reference_t<Type>>>::value()} {}
- /**
- * @brief Type index.
- * @return Type index.
- */
- [[nodiscard]] constexpr id_type index() const ENTT_NOEXCEPT {
- return seq;
- }
- /**
- * @brief Type hash.
- * @return Type hash.
- */
- [[nodiscard]] constexpr id_type hash() const ENTT_NOEXCEPT {
- return identifier;
- }
- /**
- * @brief Type name.
- * @return Type name.
- */
- [[nodiscard]] constexpr std::string_view name() const ENTT_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]] inline constexpr bool operator==(const type_info &lhs, const type_info &rhs) ENTT_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]] inline constexpr bool operator!=(const type_info &lhs, const type_info &rhs) ENTT_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) ENTT_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) ENTT_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) ENTT_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) ENTT_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() ENTT_NOEXCEPT {
- if constexpr(std::is_same_v<Type, std::remove_cv_t<std::remove_reference_t<Type>>>) {
- static type_info instance{std::in_place_type<Type>};
- return instance;
- } else {
- return type_id<std::remove_cv_t<std::remove_reference_t<Type>>>();
- }
- }
- /*! @copydoc type_id */
- template<typename Type>
- [[nodiscard]] const type_info &type_id(Type &&) ENTT_NOEXCEPT {
- return type_id<std::remove_cv_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 <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.
- * @tparam The size of the type if `sizeof` accepts it, 0 otherwise.
- */
- 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))>>
- : 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 Type First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<std::size_t Index, typename Type, typename... Other>
- struct type_list_element<Index, type_list<Type, Other...>>
- : type_list_element<Index - 1u, type_list<Other...>> {};
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam Type First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<typename Type, typename... Other>
- struct type_list_element<0u, type_list<Type, Other...>> {
- /*! @brief Searched type. */
- using type = Type;
- };
- /**
- * @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 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;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename>
- struct type_list_unique;
- /**
- * @brief Removes duplicates types from a type list.
- * @tparam Type One of the types provided by the given type list.
- * @tparam Other The other types provided by the given type list.
- */
- template<typename Type, typename... Other>
- struct type_list_unique<type_list<Type, Other...>> {
- /*! @brief A type list without duplicate types. */
- using type = std::conditional_t<
- (std::is_same_v<Type, Other> || ...),
- typename type_list_unique<type_list<Other...>>::type,
- type_list_cat_t<type_list<Type>, typename type_list_unique<type_list<Other...>>::type>>;
- };
- /*! @brief Removes duplicates types from a type list. */
- template<>
- struct type_list_unique<type_list<>> {
- /*! @brief A type list without duplicate types. */
- using type = type_list<>;
- };
- /**
- * @brief Helper type.
- * @tparam Type A type list.
- */
- template<typename Type>
- using type_list_unique_t = typename type_list_unique<Type>::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::disjunction<std::is_same<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 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 value. */
- static constexpr auto value = Value;
- };
- /**
- * @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 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 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
- * Internal details not to be documented.
- */
- 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
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /*! @copydoc is_iterator */
- template<typename Type>
- struct is_iterator<Type, std::enable_if_t<!std::is_same_v<std::remove_const_t<std::remove_pointer_t<Type>>, void>>>
- : 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::conjunction<std::is_empty<Type>, std::negation<std::is_final<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;
- /**
- * @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, typename = void>
- struct is_equality_comparable: std::false_type {};
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- 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 Type, std::size_t... Index>
- [[nodiscard]] constexpr bool unpack_maybe_equality_comparable(std::index_sequence<Index...>) {
- return (is_equality_comparable<std::tuple_element_t<Index, Type>>::value && ...);
- }
- template<typename>
- [[nodiscard]] constexpr bool maybe_equality_comparable(choice_t<0>) {
- return true;
- }
- template<typename Type>
- [[nodiscard]] constexpr auto maybe_equality_comparable(choice_t<1>) -> decltype(std::declval<typename Type::value_type>(), bool{}) {
- if constexpr(is_iterator_v<Type>) {
- return true;
- } else if constexpr(std::is_same_v<typename Type::value_type, Type>) {
- return maybe_equality_comparable<Type>(choice<0>);
- } else {
- return is_equality_comparable<typename Type::value_type>::value;
- }
- }
- template<typename Type>
- [[nodiscard]] constexpr std::enable_if_t<is_complete_v<std::tuple_size<std::remove_const_t<Type>>>, bool> maybe_equality_comparable(choice_t<2>) {
- if constexpr(has_tuple_size_value<Type>::value) {
- return unpack_maybe_equality_comparable<Type>(std::make_index_sequence<std::tuple_size<Type>::value>{});
- } else {
- return maybe_equality_comparable<Type>(choice<1>);
- }
- }
- } // namespace internal
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /*! @copydoc is_equality_comparable */
- template<typename Type>
- struct is_equality_comparable<Type, std::void_t<decltype(std::declval<Type>() == std::declval<Type>())>>
- : std::bool_constant<internal::maybe_equality_comparable<Type>(choice<2>)> {};
- /**
- * @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 = std::add_const_t<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;
- } // namespace entt
- #endif
- namespace entt {
- /**
- * @brief A SBO friendly, type-safe container for single values of any type.
- * @tparam Len Size of the storage reserved for the small buffer optimization.
- * @tparam Align Optional alignment requirement.
- */
- template<std::size_t Len, std::size_t Align>
- class basic_any {
- enum class operation : std::uint8_t {
- copy,
- move,
- transfer,
- assign,
- destroy,
- compare,
- get
- };
- enum class policy : std::uint8_t {
- owner,
- ref,
- cref
- };
- using storage_type = std::aligned_storage_t<Len + !Len, Align>;
- using vtable_type = const void *(const operation, const basic_any &, const void *);
- template<typename Type>
- static constexpr bool in_situ = Len && alignof(Type) <= alignof(storage_type) && sizeof(Type) <= sizeof(storage_type) && std::is_nothrow_move_constructible_v<Type>;
- template<typename Type>
- static const void *basic_vtable([[maybe_unused]] const operation op, [[maybe_unused]] const basic_any &value, [[maybe_unused]] const void *other) {
- static_assert(!std::is_same_v<Type, void> && std::is_same_v<std::remove_cv_t<std::remove_reference_t<Type>>, Type>, "Invalid type");
- const Type *element = nullptr;
- if constexpr(in_situ<Type>) {
- element = value.owner() ? reinterpret_cast<const Type *>(&value.storage) : static_cast<const Type *>(value.instance);
- } else {
- element = static_cast<const Type *>(value.instance);
- }
- switch(op) {
- case operation::copy:
- if constexpr(std::is_copy_constructible_v<Type>) {
- static_cast<basic_any *>(const_cast<void *>(other))->initialize<Type>(*element);
- }
- break;
- case operation::move:
- if constexpr(in_situ<Type>) {
- if(value.owner()) {
- return new(&static_cast<basic_any *>(const_cast<void *>(other))->storage) Type{std::move(*const_cast<Type *>(element))};
- }
- }
- return (static_cast<basic_any *>(const_cast<void *>(other))->instance = std::exchange(const_cast<basic_any &>(value).instance, nullptr));
- case operation::transfer:
- if constexpr(std::is_move_assignable_v<Type>) {
- *const_cast<Type *>(element) = std::move(*static_cast<Type *>(const_cast<void *>(other)));
- return other;
- }
- [[fallthrough]];
- case operation::assign:
- if constexpr(std::is_copy_assignable_v<Type>) {
- *const_cast<Type *>(element) = *static_cast<const Type *>(other);
- return other;
- }
- break;
- case operation::destroy:
- if constexpr(in_situ<Type>) {
- element->~Type();
- } else if constexpr(std::is_array_v<Type>) {
- delete[] element;
- } else {
- delete element;
- }
- break;
- case operation::compare:
- if constexpr(!std::is_function_v<Type> && !std::is_array_v<Type> && is_equality_comparable_v<Type>) {
- return *static_cast<const Type *>(element) == *static_cast<const Type *>(other) ? other : nullptr;
- } else {
- return (element == other) ? other : nullptr;
- }
- case operation::get:
- return element;
- }
- return nullptr;
- }
- template<typename Type, typename... Args>
- void initialize([[maybe_unused]] Args &&...args) {
- if constexpr(!std::is_void_v<Type>) {
- info = &type_id<std::remove_cv_t<std::remove_reference_t<Type>>>();
- vtable = basic_vtable<std::remove_cv_t<std::remove_reference_t<Type>>>;
- if constexpr(std::is_lvalue_reference_v<Type>) {
- static_assert(sizeof...(Args) == 1u && (std::is_lvalue_reference_v<Args> && ...), "Invalid arguments");
- mode = std::is_const_v<std::remove_reference_t<Type>> ? policy::cref : policy::ref;
- instance = (std::addressof(args), ...);
- } else if constexpr(in_situ<Type>) {
- if constexpr(sizeof...(Args) != 0u && std::is_aggregate_v<Type>) {
- new(&storage) Type{std::forward<Args>(args)...};
- } else {
- new(&storage) Type(std::forward<Args>(args)...);
- }
- } else {
- if constexpr(sizeof...(Args) != 0u && std::is_aggregate_v<Type>) {
- instance = new Type{std::forward<Args>(args)...};
- } else {
- instance = new Type(std::forward<Args>(args)...);
- }
- }
- }
- }
- basic_any(const basic_any &other, const policy pol) ENTT_NOEXCEPT
- : instance{other.data()},
- info{other.info},
- vtable{other.vtable},
- mode{pol} {}
- public:
- /*! @brief Size of the internal storage. */
- static constexpr auto length = Len;
- /*! @brief Alignment requirement. */
- static constexpr auto alignment = Align;
- /*! @brief Default constructor. */
- constexpr basic_any() ENTT_NOEXCEPT
- : instance{},
- info{&type_id<void>()},
- vtable{},
- mode{policy::owner} {}
- /**
- * @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)
- : basic_any{} {
- initialize<Type>(std::forward<Args>(args)...);
- }
- /**
- * @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{} {
- initialize<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{} {
- if(other.vtable) {
- other.vtable(operation::copy, other, this);
- }
- }
- /**
- * @brief Move constructor.
- * @param other The instance to move from.
- */
- basic_any(basic_any &&other) ENTT_NOEXCEPT
- : instance{},
- info{other.info},
- vtable{other.vtable},
- mode{other.mode} {
- if(other.vtable) {
- other.vtable(operation::move, other, this);
- }
- }
- /*! @brief Frees the internal storage, whatever it means. */
- ~basic_any() {
- if(vtable && owner()) {
- vtable(operation::destroy, *this, nullptr);
- }
- }
- /**
- * @brief Copy assignment operator.
- * @param other The instance to copy from.
- * @return This any object.
- */
- basic_any &operator=(const basic_any &other) {
- reset();
- if(other.vtable) {
- other.vtable(operation::copy, other, this);
- }
- return *this;
- }
- /**
- * @brief Move assignment operator.
- * @param other The instance to move from.
- * @return This any object.
- */
- basic_any &operator=(basic_any &&other) ENTT_NOEXCEPT {
- reset();
- if(other.vtable) {
- other.vtable(operation::move, other, this);
- info = other.info;
- vtable = other.vtable;
- 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>
- 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 the object type if any, `type_id<void>()` otherwise.
- * @return The object type if any, `type_id<void>()` otherwise.
- */
- [[nodiscard]] const type_info &type() const ENTT_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 ENTT_NOEXCEPT {
- return vtable ? vtable(operation::get, *this, nullptr) : nullptr;
- }
- /**
- * @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 ENTT_NOEXCEPT {
- return *info == req ? data() : nullptr;
- }
- /**
- * @brief Returns an opaque pointer to the contained instance.
- * @return An opaque pointer the contained instance, if any.
- */
- [[nodiscard]] void *data() ENTT_NOEXCEPT {
- return (!vtable || mode == policy::cref) ? nullptr : const_cast<void *>(vtable(operation::get, *this, nullptr));
- }
- /**
- * @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) ENTT_NOEXCEPT {
- return *info == req ? data() : nullptr;
- }
- /**
- * @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) {
- reset();
- 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 any &other) {
- if(vtable && mode != policy::cref && *info == *other.info) {
- return (vtable(operation::assign, *this, other.data()) != nullptr);
- }
- return false;
- }
- /*! @copydoc assign */
- bool assign(any &&other) {
- if(vtable && mode != policy::cref && *info == *other.info) {
- if(auto *val = other.data(); val) {
- return (vtable(operation::transfer, *this, val) != nullptr);
- } else {
- return (vtable(operation::assign, *this, std::as_const(other).data()) != nullptr);
- }
- }
- return false;
- }
- /*! @brief Destroys contained object */
- void reset() {
- if(vtable && owner()) {
- vtable(operation::destroy, *this, nullptr);
- }
- info = &type_id<void>();
- vtable = nullptr;
- mode = policy::owner;
- }
- /**
- * @brief Returns false if a wrapper is empty, true otherwise.
- * @return False if the wrapper is empty, true otherwise.
- */
- [[nodiscard]] explicit operator bool() const ENTT_NOEXCEPT {
- return vtable != nullptr;
- }
- /**
- * @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.
- */
- bool operator==(const basic_any &other) const ENTT_NOEXCEPT {
- if(vtable && *info == *other.info) {
- return (vtable(operation::compare, *this, other.data()) != nullptr);
- }
- return (!vtable && !other.vtable);
- }
- /**
- * @brief Aliasing constructor.
- * @return A wrapper that shares a reference to an unmanaged object.
- */
- [[nodiscard]] basic_any as_ref() ENTT_NOEXCEPT {
- return basic_any{*this, (mode == policy::cref ? policy::cref : policy::ref)};
- }
- /*! @copydoc as_ref */
- [[nodiscard]] basic_any as_ref() const ENTT_NOEXCEPT {
- return basic_any{*this, policy::cref};
- }
- /**
- * @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 ENTT_NOEXCEPT {
- return (mode == policy::owner);
- }
- private:
- union {
- const void *instance;
- storage_type storage;
- };
- const type_info *info;
- vtable_type *vtable;
- policy mode;
- };
- /**
- * @brief Checks if two wrappers differ in their content.
- * @tparam Len Size of the storage reserved for the small buffer optimization.
- * @tparam Align Alignment requirement.
- * @param lhs A wrapper, either empty or not.
- * @param rhs A wrapper, either empty or not.
- * @return True if the two wrappers differ in their content, false otherwise.
- */
- template<std::size_t Len, std::size_t Align>
- [[nodiscard]] inline bool operator!=(const basic_any<Len, Align> &lhs, const basic_any<Len, Align> &rhs) ENTT_NOEXCEPT {
- return !(lhs == rhs);
- }
- /**
- * @brief Performs type-safe access to the contained object.
- * @tparam Type Type to which conversion is required.
- * @tparam Len Size of the storage 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>
- Type any_cast(const basic_any<Len, Align> &data) ENTT_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>
- Type any_cast(basic_any<Len, Align> &data) ENTT_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>
- Type any_cast(basic_any<Len, Align> &&data) ENTT_NOEXCEPT {
- if constexpr(std::is_copy_constructible_v<std::remove_cv_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));
- } else {
- 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>
- const Type *any_cast(const basic_any<Len, Align> *data) ENTT_NOEXCEPT {
- const auto &info = type_id<std::remove_cv_t<std::remove_reference_t<Type>>>();
- return static_cast<const Type *>(data->data(info));
- }
- /*! @copydoc any_cast */
- template<typename Type, std::size_t Len, std::size_t Align>
- Type *any_cast(basic_any<Len, Align> *data) ENTT_NOEXCEPT {
- const auto &info = type_id<std::remove_cv_t<std::remove_reference_t<Type>>>();
- // last attempt to make wrappers for const references return their values
- return static_cast<Type *>(static_cast<constness_as_t<basic_any<Len, Align>, Type> *>(data)->data(info));
- }
- /**
- * @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 storage 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>
- 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 storage 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>
- basic_any<Len, Align> forward_as_any(Type &&value) {
- return basic_any<Len, Align>{std::in_place_type<std::conditional_t<std::is_rvalue_reference_v<Type>, std::decay_t<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 "../core/attribute.h"
- // #include "fwd.hpp"
- // #include "hashed_string.hpp"
- namespace entt {
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- namespace internal {
- struct ENTT_API type_index final {
- [[nodiscard]] static id_type next() ENTT_NOEXCEPT {
- static ENTT_MAYBE_ATOMIC(id_type) value{};
- return value++;
- }
- };
- template<typename Type>
- [[nodiscard]] constexpr auto stripped_type_name() ENTT_NOEXCEPT {
- #if defined ENTT_PRETTY_FUNCTION
- std::string_view pretty_function{ENTT_PRETTY_FUNCTION};
- auto first = pretty_function.find_first_not_of(' ', pretty_function.find_first_of(ENTT_PRETTY_FUNCTION_PREFIX) + 1);
- auto value = pretty_function.substr(first, pretty_function.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]] static constexpr std::string_view type_name(int) ENTT_NOEXCEPT {
- constexpr auto value = stripped_type_name<Type>();
- return value;
- }
- template<typename Type>
- [[nodiscard]] static std::string_view type_name(char) ENTT_NOEXCEPT {
- static const auto value = stripped_type_name<Type>();
- return value;
- }
- template<typename Type, auto = stripped_type_name<Type>().find_first_of('.')>
- [[nodiscard]] static constexpr id_type type_hash(int) ENTT_NOEXCEPT {
- constexpr auto stripped = stripped_type_name<Type>();
- constexpr auto value = hashed_string::value(stripped.data(), stripped.size());
- return value;
- }
- template<typename Type>
- [[nodiscard]] static id_type type_hash(char) ENTT_NOEXCEPT {
- static const auto value = [](const auto stripped) {
- return hashed_string::value(stripped.data(), stripped.size());
- }(stripped_type_name<Type>());
- return value;
- }
- } // namespace internal
- /**
- * Internal details not to be documented.
- * @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() ENTT_NOEXCEPT {
- static const id_type value = internal::type_index::next();
- return value;
- }
- /*! @copydoc value */
- [[nodiscard]] constexpr operator id_type() const ENTT_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() ENTT_NOEXCEPT {
- return internal::type_hash<Type>(0);
- #else
- [[nodiscard]] static constexpr id_type value() ENTT_NOEXCEPT {
- return type_index<Type>::value();
- #endif
- }
- /*! @copydoc value */
- [[nodiscard]] constexpr operator id_type() const ENTT_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() ENTT_NOEXCEPT {
- return internal::type_name<Type>(0);
- }
- /*! @copydoc value */
- [[nodiscard]] constexpr operator std::string_view() const ENTT_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>
- constexpr type_info(std::in_place_type_t<Type>) ENTT_NOEXCEPT
- : seq{type_index<std::remove_cv_t<std::remove_reference_t<Type>>>::value()},
- identifier{type_hash<std::remove_cv_t<std::remove_reference_t<Type>>>::value()},
- alias{type_name<std::remove_cv_t<std::remove_reference_t<Type>>>::value()} {}
- /**
- * @brief Type index.
- * @return Type index.
- */
- [[nodiscard]] constexpr id_type index() const ENTT_NOEXCEPT {
- return seq;
- }
- /**
- * @brief Type hash.
- * @return Type hash.
- */
- [[nodiscard]] constexpr id_type hash() const ENTT_NOEXCEPT {
- return identifier;
- }
- /**
- * @brief Type name.
- * @return Type name.
- */
- [[nodiscard]] constexpr std::string_view name() const ENTT_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]] inline constexpr bool operator==(const type_info &lhs, const type_info &rhs) ENTT_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]] inline constexpr bool operator!=(const type_info &lhs, const type_info &rhs) ENTT_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) ENTT_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) ENTT_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) ENTT_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) ENTT_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() ENTT_NOEXCEPT {
- if constexpr(std::is_same_v<Type, std::remove_cv_t<std::remove_reference_t<Type>>>) {
- static type_info instance{std::in_place_type<Type>};
- return instance;
- } else {
- return type_id<std::remove_cv_t<std::remove_reference_t<Type>>>();
- }
- }
- /*! @copydoc type_id */
- template<typename Type>
- [[nodiscard]] const type_info &type_id(Type &&) ENTT_NOEXCEPT {
- return type_id<std::remove_cv_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 <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.
- * @tparam The size of the type if `sizeof` accepts it, 0 otherwise.
- */
- 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))>>
- : 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 Type First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<std::size_t Index, typename Type, typename... Other>
- struct type_list_element<Index, type_list<Type, Other...>>
- : type_list_element<Index - 1u, type_list<Other...>> {};
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam Type First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<typename Type, typename... Other>
- struct type_list_element<0u, type_list<Type, Other...>> {
- /*! @brief Searched type. */
- using type = Type;
- };
- /**
- * @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 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;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename>
- struct type_list_unique;
- /**
- * @brief Removes duplicates types from a type list.
- * @tparam Type One of the types provided by the given type list.
- * @tparam Other The other types provided by the given type list.
- */
- template<typename Type, typename... Other>
- struct type_list_unique<type_list<Type, Other...>> {
- /*! @brief A type list without duplicate types. */
- using type = std::conditional_t<
- (std::is_same_v<Type, Other> || ...),
- typename type_list_unique<type_list<Other...>>::type,
- type_list_cat_t<type_list<Type>, typename type_list_unique<type_list<Other...>>::type>>;
- };
- /*! @brief Removes duplicates types from a type list. */
- template<>
- struct type_list_unique<type_list<>> {
- /*! @brief A type list without duplicate types. */
- using type = type_list<>;
- };
- /**
- * @brief Helper type.
- * @tparam Type A type list.
- */
- template<typename Type>
- using type_list_unique_t = typename type_list_unique<Type>::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::disjunction<std::is_same<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 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 value. */
- static constexpr auto value = Value;
- };
- /**
- * @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 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 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
- * Internal details not to be documented.
- */
- 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
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /*! @copydoc is_iterator */
- template<typename Type>
- struct is_iterator<Type, std::enable_if_t<!std::is_same_v<std::remove_const_t<std::remove_pointer_t<Type>>, void>>>
- : 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::conjunction<std::is_empty<Type>, std::negation<std::is_final<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;
- /**
- * @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, typename = void>
- struct is_equality_comparable: std::false_type {};
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- 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 Type, std::size_t... Index>
- [[nodiscard]] constexpr bool unpack_maybe_equality_comparable(std::index_sequence<Index...>) {
- return (is_equality_comparable<std::tuple_element_t<Index, Type>>::value && ...);
- }
- template<typename>
- [[nodiscard]] constexpr bool maybe_equality_comparable(choice_t<0>) {
- return true;
- }
- template<typename Type>
- [[nodiscard]] constexpr auto maybe_equality_comparable(choice_t<1>) -> decltype(std::declval<typename Type::value_type>(), bool{}) {
- if constexpr(is_iterator_v<Type>) {
- return true;
- } else if constexpr(std::is_same_v<typename Type::value_type, Type>) {
- return maybe_equality_comparable<Type>(choice<0>);
- } else {
- return is_equality_comparable<typename Type::value_type>::value;
- }
- }
- template<typename Type>
- [[nodiscard]] constexpr std::enable_if_t<is_complete_v<std::tuple_size<std::remove_const_t<Type>>>, bool> maybe_equality_comparable(choice_t<2>) {
- if constexpr(has_tuple_size_value<Type>::value) {
- return unpack_maybe_equality_comparable<Type>(std::make_index_sequence<std::tuple_size<Type>::value>{});
- } else {
- return maybe_equality_comparable<Type>(choice<1>);
- }
- }
- } // namespace internal
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /*! @copydoc is_equality_comparable */
- template<typename Type>
- struct is_equality_comparable<Type, std::void_t<decltype(std::declval<Type>() == std::declval<Type>())>>
- : std::bool_constant<internal::maybe_equality_comparable<Type>(choice<2>)> {};
- /**
- * @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 = std::add_const_t<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;
- } // namespace entt
- #endif
- // #include "fwd.hpp"
- #ifndef ENTT_POLY_FWD_HPP
- #define ENTT_POLY_FWD_HPP
- #include <cstdint>
- #include <type_traits>
- namespace entt {
- template<typename, std::size_t Len = sizeof(double[2]), std::size_t = alignof(typename std::aligned_storage_t<Len + !Len>)>
- 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<class 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>
- poly_inspector invoke(Args &&...args) const;
- /*! @copydoc invoke */
- template<std::size_t Member, typename... Args>
- 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... Args>
- static auto vtable_entry(Ret (*)(inspector &, Args...)) -> Ret (*)(basic_any<Len, Align> &, Args...);
- template<typename Ret, typename... Args>
- static auto vtable_entry(Ret (*)(const inspector &, Args...)) -> Ret (*)(const basic_any<Len, Align> &, Args...);
- template<typename Ret, typename... Args>
- static auto vtable_entry(Ret (*)(Args...)) -> Ret (*)(const basic_any<Len, Align> &, Args...);
- template<typename Ret, typename... Args>
- static auto vtable_entry(Ret (inspector::*)(Args...)) -> Ret (*)(basic_any<Len, Align> &, Args...);
- template<typename Ret, typename... Args>
- static auto vtable_entry(Ret (inspector::*)(Args...) const) -> Ret (*)(const basic_any<Len, Align> &, Args...);
- template<auto... Candidate>
- static auto make_vtable(value_list<Candidate...>) ENTT_NOEXCEPT
- -> decltype(std::make_tuple(vtable_entry(Candidate)...));
- template<typename... Func>
- [[nodiscard]] static constexpr auto make_vtable(type_list<Func...>) ENTT_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...)) ENTT_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...>) ENTT_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_v = std::tuple_size_v<vtable_type> == 1u;
- public:
- /*! @brief Virtual table type. */
- using type = std::conditional_t<is_mono_v, 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() ENTT_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_v) {
- 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>>> {
- /*! @brief A poly base is allowed to snoop into a poly object. */
- 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() ENTT_NOEXCEPT
- : storage{},
- vtable{} {}
- /**
- * @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_cv_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_cv_t<std::remove_reference_t<Type>>, basic_poly>>>
- basic_poly(Type &&value) ENTT_NOEXCEPT
- : basic_poly{std::in_place_type<std::remove_cv_t<std::remove_reference_t<Type>>>, std::forward<Type>(value)} {}
- /**
- * @brief Returns the object type if any, `type_id<void>()` otherwise.
- * @return The object type if any, `type_id<void>()` otherwise.
- */
- [[nodiscard]] const type_info &type() const ENTT_NOEXCEPT {
- return storage.type();
- }
- /**
- * @brief Returns an opaque pointer to the contained instance.
- * @return An opaque pointer the contained instance, if any.
- */
- [[nodiscard]] const void *data() const ENTT_NOEXCEPT {
- return storage.data();
- }
- /*! @copydoc data */
- [[nodiscard]] void *data() ENTT_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_cv_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 ENTT_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->() ENTT_NOEXCEPT {
- return this;
- }
- /*! @copydoc operator-> */
- [[nodiscard]] const concept_type *operator->() const ENTT_NOEXCEPT {
- return this;
- }
- /**
- * @brief Aliasing constructor.
- * @return A poly that shares a reference to an unmanaged object.
- */
- [[nodiscard]] basic_poly as_ref() ENTT_NOEXCEPT {
- basic_poly ref{};
- ref.storage = storage.as_ref();
- ref.vtable = vtable;
- return ref;
- }
- /*! @copydoc as_ref */
- [[nodiscard]] basic_poly as_ref() const ENTT_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 <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
- #define ENTT_STR(arg) #arg
- #define ENTT_XSTR(arg) ENTT_STR(arg)
- #endif
- #define ENTT_VERSION_MAJOR 3
- #define ENTT_VERSION_MINOR 10
- #define ENTT_VERSION_PATCH 3
- #define ENTT_VERSION \
- ENTT_XSTR(ENTT_VERSION_MAJOR) \
- "." ENTT_XSTR(ENTT_VERSION_MINOR) "." ENTT_XSTR(ENTT_VERSION_PATCH)
- #endif
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #ifndef ENTT_NOEXCEPT
- # define ENTT_NOEXCEPT noexcept
- # define ENTT_NOEXCEPT_IF(expr) noexcept(expr)
- # else
- # define ENTT_NOEXCEPT_IF(...)
- #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
- #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(...) (void(0))
- #elif !defined ENTT_ASSERT
- # include <cassert>
- # define ENTT_ASSERT(condition, ...) assert(condition)
- #endif
- #ifdef ENTT_NO_ETO
- # define ENTT_IGNORE_IF_EMPTY false
- #else
- # define ENTT_IGNORE_IF_EMPTY true
- #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
- #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
- #endif
- namespace entt {
- /**
- * @brief Base class for processes.
- *
- * This class stays true to the CRTP idiom. Derived classes must specify what's
- * the intended type for elapsed times.<br/>
- * A process should expose publicly the following member functions whether
- * required:
- *
- * * @code{.cpp}
- * void update(Delta, void *);
- * @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 init();
- * @endcode
- *
- * It's invoked when the process joins the running queue of a scheduler. This
- * happens as soon as it's attached to the scheduler if the process is a top
- * level one, otherwise when it replaces its parent if the process is a
- * continuation.
- *
- * * @code{.cpp}
- * void succeeded();
- * @endcode
- *
- * It's invoked in case of success, immediately after an update and during the
- * same tick.
- *
- * * @code{.cpp}
- * void failed();
- * @endcode
- *
- * It's invoked in case of errors, immediately after an update and during the
- * same tick.
- *
- * * @code{.cpp}
- * void aborted();
- * @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` protected member functions and even pause or unpause the
- * process itself.
- *
- * @sa scheduler
- *
- * @tparam Derived Actual type of process that extends the class template.
- * @tparam Delta Type to use to provide elapsed time.
- */
- template<typename Derived, typename Delta>
- class process {
- enum class state : std::uint8_t {
- uninitialized = 0,
- running,
- paused,
- succeeded,
- failed,
- aborted,
- finished,
- rejected
- };
- template<typename Target = Derived>
- auto next(std::integral_constant<state, state::uninitialized>)
- -> decltype(std::declval<Target>().init(), void()) {
- static_cast<Target *>(this)->init();
- }
- template<typename Target = Derived>
- auto next(std::integral_constant<state, state::running>, Delta delta, void *data)
- -> decltype(std::declval<Target>().update(delta, data), void()) {
- static_cast<Target *>(this)->update(delta, data);
- }
- template<typename Target = Derived>
- auto next(std::integral_constant<state, state::succeeded>)
- -> decltype(std::declval<Target>().succeeded(), void()) {
- static_cast<Target *>(this)->succeeded();
- }
- template<typename Target = Derived>
- auto next(std::integral_constant<state, state::failed>)
- -> decltype(std::declval<Target>().failed(), void()) {
- static_cast<Target *>(this)->failed();
- }
- template<typename Target = Derived>
- auto next(std::integral_constant<state, state::aborted>)
- -> decltype(std::declval<Target>().aborted(), void()) {
- static_cast<Target *>(this)->aborted();
- }
- void next(...) const ENTT_NOEXCEPT {}
- protected:
- /**
- * @brief Terminates a process with success if it's still alive.
- *
- * The function is idempotent and it does nothing if the process isn't
- * alive.
- */
- void succeed() ENTT_NOEXCEPT {
- if(alive()) {
- current = state::succeeded;
- }
- }
- /**
- * @brief Terminates a process with errors if it's still alive.
- *
- * The function is idempotent and it does nothing if the process isn't
- * alive.
- */
- void fail() ENTT_NOEXCEPT {
- if(alive()) {
- current = state::failed;
- }
- }
- /**
- * @brief Stops a process if it's in a running state.
- *
- * The function is idempotent and it does nothing if the process isn't
- * running.
- */
- void pause() ENTT_NOEXCEPT {
- if(current == state::running) {
- current = state::paused;
- }
- }
- /**
- * @brief Restarts a process if it's paused.
- *
- * The function is idempotent and it does nothing if the process isn't
- * paused.
- */
- void unpause() ENTT_NOEXCEPT {
- if(current == state::paused) {
- current = state::running;
- }
- }
- public:
- /*! @brief Type used to provide elapsed time. */
- using delta_type = Delta;
- /*! @brief Default destructor. */
- virtual ~process() ENTT_NOEXCEPT {
- static_assert(std::is_base_of_v<process, Derived>, "Incorrect use of the class template");
- }
- /**
- * @brief Aborts a process if it's still alive.
- *
- * The function is idempotent and it does nothing if the process isn't
- * alive.
- *
- * @param immediately Requests an immediate operation.
- */
- void abort(const bool immediately = false) {
- if(alive()) {
- current = state::aborted;
- if(immediately) {
- tick({});
- }
- }
- }
- /**
- * @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 ENTT_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 ENTT_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 ENTT_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 ENTT_NOEXCEPT {
- return current == state::rejected;
- }
- /**
- * @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::uninitialized:
- next(std::integral_constant<state, state::uninitialized>{});
- current = state::running;
- break;
- case state::running:
- next(std::integral_constant<state, state::running>{}, delta, data);
- break;
- default:
- // suppress warnings
- break;
- }
- // if it's dead, it must be notified and removed immediately
- switch(current) {
- case state::succeeded:
- next(std::integral_constant<state, state::succeeded>{});
- current = state::finished;
- break;
- case state::failed:
- next(std::integral_constant<state, state::failed>{});
- current = state::rejected;
- break;
- case state::aborted:
- next(std::integral_constant<state, state::aborted>{});
- current = state::rejected;
- break;
- default:
- // suppress warnings
- break;
- }
- }
- private:
- state current{state::uninitialized};
- };
- /**
- * @brief Adaptor for lambdas and functors to turn them into processes.
- *
- * Lambdas and functors can't be used directly with a scheduler for they are not
- * properly defined processes with managed life cycles.<br/>
- * This class helps in filling the gap and turning lambdas and functors into
- * full featured processes usable by a scheduler.
- *
- * The signature of the function call operator should be equivalent to the
- * following:
- *
- * @code{.cpp}
- * void(Delta delta, void *data, auto succeed, auto fail);
- * @endcode
- *
- * Where:
- *
- * * `delta` is the elapsed time.
- * * `data` is an opaque pointer to user data if any, `nullptr` otherwise.
- * * `succeed` is a function to call when a process terminates with success.
- * * `fail` is a function to call when a process terminates with errors.
- *
- * The signature of the function call operator of both `succeed` and `fail`
- * is equivalent to the following:
- *
- * @code{.cpp}
- * void();
- * @endcode
- *
- * Usually users shouldn't worry about creating adaptors. A scheduler will
- * create them internally each and avery time a lambda or a functor is used as
- * a process.
- *
- * @sa process
- * @sa scheduler
- *
- * @tparam Func Actual type of process.
- * @tparam Delta Type to use to provide elapsed time.
- */
- template<typename Func, typename Delta>
- struct process_adaptor: process<process_adaptor<Func, Delta>, Delta>, private Func {
- /**
- * @brief Constructs a process adaptor from a lambda or a functor.
- * @tparam Args Types of arguments to use to initialize the actual process.
- * @param args Parameters to use to initialize the actual process.
- */
- template<typename... Args>
- process_adaptor(Args &&...args)
- : Func{std::forward<Args>(args)...} {}
- /**
- * @brief Updates a process and its internal state if required.
- * @param delta Elapsed time.
- * @param data Optional data.
- */
- void update(const Delta delta, void *data) {
- Func::operator()(
- delta,
- data,
- [this]() { this->succeed(); },
- [this]() { this->fail(); });
- }
- };
- } // namespace entt
- #endif
- // #include "process/scheduler.hpp"
- #ifndef ENTT_PROCESS_SCHEDULER_HPP
- #define ENTT_PROCESS_SCHEDULER_HPP
- #include <algorithm>
- #include <iterator>
- #include <memory>
- #include <type_traits>
- #include <utility>
- #include <vector>
- // #include "../config/config.h"
- // #include "process.hpp"
- #ifndef ENTT_PROCESS_PROCESS_HPP
- #define ENTT_PROCESS_PROCESS_HPP
- #include <cstdint>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- namespace entt {
- /**
- * @brief Base class for processes.
- *
- * This class stays true to the CRTP idiom. Derived classes must specify what's
- * the intended type for elapsed times.<br/>
- * A process should expose publicly the following member functions whether
- * required:
- *
- * * @code{.cpp}
- * void update(Delta, void *);
- * @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 init();
- * @endcode
- *
- * It's invoked when the process joins the running queue of a scheduler. This
- * happens as soon as it's attached to the scheduler if the process is a top
- * level one, otherwise when it replaces its parent if the process is a
- * continuation.
- *
- * * @code{.cpp}
- * void succeeded();
- * @endcode
- *
- * It's invoked in case of success, immediately after an update and during the
- * same tick.
- *
- * * @code{.cpp}
- * void failed();
- * @endcode
- *
- * It's invoked in case of errors, immediately after an update and during the
- * same tick.
- *
- * * @code{.cpp}
- * void aborted();
- * @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` protected member functions and even pause or unpause the
- * process itself.
- *
- * @sa scheduler
- *
- * @tparam Derived Actual type of process that extends the class template.
- * @tparam Delta Type to use to provide elapsed time.
- */
- template<typename Derived, typename Delta>
- class process {
- enum class state : std::uint8_t {
- uninitialized = 0,
- running,
- paused,
- succeeded,
- failed,
- aborted,
- finished,
- rejected
- };
- template<typename Target = Derived>
- auto next(std::integral_constant<state, state::uninitialized>)
- -> decltype(std::declval<Target>().init(), void()) {
- static_cast<Target *>(this)->init();
- }
- template<typename Target = Derived>
- auto next(std::integral_constant<state, state::running>, Delta delta, void *data)
- -> decltype(std::declval<Target>().update(delta, data), void()) {
- static_cast<Target *>(this)->update(delta, data);
- }
- template<typename Target = Derived>
- auto next(std::integral_constant<state, state::succeeded>)
- -> decltype(std::declval<Target>().succeeded(), void()) {
- static_cast<Target *>(this)->succeeded();
- }
- template<typename Target = Derived>
- auto next(std::integral_constant<state, state::failed>)
- -> decltype(std::declval<Target>().failed(), void()) {
- static_cast<Target *>(this)->failed();
- }
- template<typename Target = Derived>
- auto next(std::integral_constant<state, state::aborted>)
- -> decltype(std::declval<Target>().aborted(), void()) {
- static_cast<Target *>(this)->aborted();
- }
- void next(...) const ENTT_NOEXCEPT {}
- protected:
- /**
- * @brief Terminates a process with success if it's still alive.
- *
- * The function is idempotent and it does nothing if the process isn't
- * alive.
- */
- void succeed() ENTT_NOEXCEPT {
- if(alive()) {
- current = state::succeeded;
- }
- }
- /**
- * @brief Terminates a process with errors if it's still alive.
- *
- * The function is idempotent and it does nothing if the process isn't
- * alive.
- */
- void fail() ENTT_NOEXCEPT {
- if(alive()) {
- current = state::failed;
- }
- }
- /**
- * @brief Stops a process if it's in a running state.
- *
- * The function is idempotent and it does nothing if the process isn't
- * running.
- */
- void pause() ENTT_NOEXCEPT {
- if(current == state::running) {
- current = state::paused;
- }
- }
- /**
- * @brief Restarts a process if it's paused.
- *
- * The function is idempotent and it does nothing if the process isn't
- * paused.
- */
- void unpause() ENTT_NOEXCEPT {
- if(current == state::paused) {
- current = state::running;
- }
- }
- public:
- /*! @brief Type used to provide elapsed time. */
- using delta_type = Delta;
- /*! @brief Default destructor. */
- virtual ~process() ENTT_NOEXCEPT {
- static_assert(std::is_base_of_v<process, Derived>, "Incorrect use of the class template");
- }
- /**
- * @brief Aborts a process if it's still alive.
- *
- * The function is idempotent and it does nothing if the process isn't
- * alive.
- *
- * @param immediately Requests an immediate operation.
- */
- void abort(const bool immediately = false) {
- if(alive()) {
- current = state::aborted;
- if(immediately) {
- tick({});
- }
- }
- }
- /**
- * @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 ENTT_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 ENTT_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 ENTT_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 ENTT_NOEXCEPT {
- return current == state::rejected;
- }
- /**
- * @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::uninitialized:
- next(std::integral_constant<state, state::uninitialized>{});
- current = state::running;
- break;
- case state::running:
- next(std::integral_constant<state, state::running>{}, delta, data);
- break;
- default:
- // suppress warnings
- break;
- }
- // if it's dead, it must be notified and removed immediately
- switch(current) {
- case state::succeeded:
- next(std::integral_constant<state, state::succeeded>{});
- current = state::finished;
- break;
- case state::failed:
- next(std::integral_constant<state, state::failed>{});
- current = state::rejected;
- break;
- case state::aborted:
- next(std::integral_constant<state, state::aborted>{});
- current = state::rejected;
- break;
- default:
- // suppress warnings
- break;
- }
- }
- private:
- state current{state::uninitialized};
- };
- /**
- * @brief Adaptor for lambdas and functors to turn them into processes.
- *
- * Lambdas and functors can't be used directly with a scheduler for they are not
- * properly defined processes with managed life cycles.<br/>
- * This class helps in filling the gap and turning lambdas and functors into
- * full featured processes usable by a scheduler.
- *
- * The signature of the function call operator should be equivalent to the
- * following:
- *
- * @code{.cpp}
- * void(Delta delta, void *data, auto succeed, auto fail);
- * @endcode
- *
- * Where:
- *
- * * `delta` is the elapsed time.
- * * `data` is an opaque pointer to user data if any, `nullptr` otherwise.
- * * `succeed` is a function to call when a process terminates with success.
- * * `fail` is a function to call when a process terminates with errors.
- *
- * The signature of the function call operator of both `succeed` and `fail`
- * is equivalent to the following:
- *
- * @code{.cpp}
- * void();
- * @endcode
- *
- * Usually users shouldn't worry about creating adaptors. A scheduler will
- * create them internally each and avery time a lambda or a functor is used as
- * a process.
- *
- * @sa process
- * @sa scheduler
- *
- * @tparam Func Actual type of process.
- * @tparam Delta Type to use to provide elapsed time.
- */
- template<typename Func, typename Delta>
- struct process_adaptor: process<process_adaptor<Func, Delta>, Delta>, private Func {
- /**
- * @brief Constructs a process adaptor from a lambda or a functor.
- * @tparam Args Types of arguments to use to initialize the actual process.
- * @param args Parameters to use to initialize the actual process.
- */
- template<typename... Args>
- process_adaptor(Args &&...args)
- : Func{std::forward<Args>(args)...} {}
- /**
- * @brief Updates a process and its internal state if required.
- * @param delta Elapsed time.
- * @param data Optional data.
- */
- void update(const Delta delta, void *data) {
- Func::operator()(
- delta,
- data,
- [this]() { this->succeed(); },
- [this]() { this->fail(); });
- }
- };
- } // 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.
- *
- * Example of use (pseudocode):
- *
- * @code{.cpp}
- * scheduler.attach([](auto delta, void *, auto succeed, auto fail) {
- * // code
- * }).then<my_process>(arguments...);
- * @endcode
- *
- * 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.
- */
- template<typename Delta>
- class scheduler {
- struct process_handler {
- using instance_type = std::unique_ptr<void, void (*)(void *)>;
- using update_fn_type = bool(scheduler &, std::size_t, Delta, void *);
- using abort_fn_type = void(scheduler &, std::size_t, bool);
- using next_type = std::unique_ptr<process_handler>;
- instance_type instance;
- update_fn_type *update;
- abort_fn_type *abort;
- next_type next;
- };
- struct continuation {
- continuation(process_handler *ref) ENTT_NOEXCEPT
- : handler{ref} {}
- template<typename Proc, typename... Args>
- continuation then(Args &&...args) {
- static_assert(std::is_base_of_v<process<Proc, Delta>, Proc>, "Invalid process type");
- auto proc = typename process_handler::instance_type{new Proc{std::forward<Args>(args)...}, &scheduler::deleter<Proc>};
- handler->next.reset(new process_handler{std::move(proc), &scheduler::update<Proc>, &scheduler::abort<Proc>, nullptr});
- handler = handler->next.get();
- return *this;
- }
- template<typename Func>
- continuation then(Func &&func) {
- return then<process_adaptor<std::decay_t<Func>, Delta>>(std::forward<Func>(func));
- }
- private:
- process_handler *handler;
- };
- template<typename Proc>
- [[nodiscard]] static bool update(scheduler &owner, std::size_t pos, const Delta delta, void *data) {
- auto *process = static_cast<Proc *>(owner.handlers[pos].instance.get());
- process->tick(delta, data);
- if(process->rejected()) {
- return true;
- } else if(process->finished()) {
- if(auto &&handler = owner.handlers[pos]; handler.next) {
- handler = std::move(*handler.next);
- // forces the process to exit the uninitialized state
- return handler.update(owner, pos, {}, nullptr);
- }
- return true;
- }
- return false;
- }
- template<typename Proc>
- static void abort(scheduler &owner, std::size_t pos, const bool immediately) {
- static_cast<Proc *>(owner.handlers[pos].instance.get())->abort(immediately);
- }
- template<typename Proc>
- static void deleter(void *proc) {
- delete static_cast<Proc *>(proc);
- }
- public:
- /*! @brief Unsigned integer type. */
- using size_type = std::size_t;
- /*! @brief Default constructor. */
- scheduler() = default;
- /*! @brief Default move constructor. */
- scheduler(scheduler &&) = default;
- /*! @brief Default move assignment operator. @return This scheduler. */
- scheduler &operator=(scheduler &&) = default;
- /**
- * @brief Number of processes currently scheduled.
- * @return Number of processes currently scheduled.
- */
- [[nodiscard]] size_type size() const ENTT_NOEXCEPT {
- return handlers.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 ENTT_NOEXCEPT {
- return handlers.empty();
- }
- /**
- * @brief Discards all scheduled processes.
- *
- * Processes aren't aborted. They are discarded along with their children
- * and never executed again.
- */
- void clear() {
- handlers.clear();
- }
- /**
- * @brief Schedules a process for the next tick.
- *
- * Returned value is an opaque object that can be used to attach a child to
- * the given process. The child is automatically scheduled when the process
- * terminates and only if the process returns with success.
- *
- * Example of use (pseudocode):
- *
- * @code{.cpp}
- * // schedules a task in the form of a process class
- * scheduler.attach<my_process>(arguments...)
- * // appends a child in the form of a lambda function
- * .then([](auto delta, void *, auto succeed, auto fail) {
- * // code
- * })
- * // appends a child in the form of another process class
- * .then<my_other_process>();
- * @endcode
- *
- * @tparam Proc Type of process to schedule.
- * @tparam Args Types of arguments to use to initialize the process.
- * @param args Parameters to use to initialize the process.
- * @return An opaque object to use to concatenate processes.
- */
- template<typename Proc, typename... Args>
- auto attach(Args &&...args) {
- static_assert(std::is_base_of_v<process<Proc, Delta>, Proc>, "Invalid process type");
- auto proc = typename process_handler::instance_type{new Proc{std::forward<Args>(args)...}, &scheduler::deleter<Proc>};
- auto &&ref = handlers.emplace_back(process_handler{std::move(proc), &scheduler::update<Proc>, &scheduler::abort<Proc>, nullptr});
- // forces the process to exit the uninitialized state
- ref.update(*this, handlers.size() - 1u, {}, nullptr);
- return continuation{&handlers.back()};
- }
- /**
- * @brief Schedules a process for the next tick.
- *
- * A process can be either a lambda or a functor. The scheduler wraps both
- * of them in a process adaptor internally.<br/>
- * The signature of the function call operator should be equivalent to the
- * following:
- *
- * @code{.cpp}
- * void(Delta delta, void *data, auto succeed, auto fail);
- * @endcode
- *
- * Where:
- *
- * * `delta` is the elapsed time.
- * * `data` is an opaque pointer to user data if any, `nullptr` otherwise.
- * * `succeed` is a function to call when a process terminates with success.
- * * `fail` is a function to call when a process terminates with errors.
- *
- * The signature of the function call operator of both `succeed` and `fail`
- * is equivalent to the following:
- *
- * @code{.cpp}
- * void();
- * @endcode
- *
- * Returned value is an opaque object that can be used to attach a child to
- * the given process. The child is automatically scheduled when the process
- * terminates and only if the process returns with success.
- *
- * Example of use (pseudocode):
- *
- * @code{.cpp}
- * // schedules a task in the form of a lambda function
- * scheduler.attach([](auto delta, void *, auto succeed, auto fail) {
- * // code
- * })
- * // appends a child in the form of another lambda function
- * .then([](auto delta, void *, auto succeed, auto fail) {
- * // code
- * })
- * // appends a child in the form of a process class
- * .then<my_process>(arguments...);
- * @endcode
- *
- * @sa process_adaptor
- *
- * @tparam Func Type of process to schedule.
- * @param func Either a lambda or a functor to use as a process.
- * @return An opaque object to use to concatenate processes.
- */
- template<typename Func>
- auto attach(Func &&func) {
- using Proc = process_adaptor<std::decay_t<Func>, Delta>;
- return attach<Proc>(std::forward<Func>(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 delta, void *data = nullptr) {
- for(auto pos = handlers.size(); pos; --pos) {
- const auto curr = pos - 1u;
- if(const auto dead = handlers[curr].update(*this, curr, delta, data); dead) {
- std::swap(handlers[curr], handlers.back());
- handlers.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 immediately Requests an immediate operation.
- */
- void abort(const bool immediately = false) {
- for(auto pos = handlers.size(); pos; --pos) {
- const auto curr = pos - 1u;
- handlers[curr].abort(*this, curr, immediately);
- }
- }
- private:
- std::vector<process_handler> 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 "../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
- #define ENTT_STR(arg) #arg
- #define ENTT_XSTR(arg) ENTT_STR(arg)
- #endif
- #define ENTT_VERSION_MAJOR 3
- #define ENTT_VERSION_MINOR 10
- #define ENTT_VERSION_PATCH 3
- #define ENTT_VERSION \
- ENTT_XSTR(ENTT_VERSION_MAJOR) \
- "." ENTT_XSTR(ENTT_VERSION_MINOR) "." ENTT_XSTR(ENTT_VERSION_PATCH)
- #endif
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #ifndef ENTT_NOEXCEPT
- # define ENTT_NOEXCEPT noexcept
- # define ENTT_NOEXCEPT_IF(expr) noexcept(expr)
- # else
- # define ENTT_NOEXCEPT_IF(...)
- #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
- #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(...) (void(0))
- #elif !defined ENTT_ASSERT
- # include <cassert>
- # define ENTT_ASSERT(condition, ...) assert(condition)
- #endif
- #ifdef ENTT_NO_ETO
- # define ENTT_IGNORE_IF_EMPTY false
- #else
- # define ENTT_IGNORE_IF_EMPTY true
- #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
- #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
- #endif
- // #include "../container/dense_map.hpp"
- #ifndef ENTT_CONTAINER_DENSE_MAP_HPP
- #define ENTT_CONTAINER_DENSE_MAP_HPP
- #include <algorithm>
- #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
- #define ENTT_STR(arg) #arg
- #define ENTT_XSTR(arg) ENTT_STR(arg)
- #endif
- #define ENTT_VERSION_MAJOR 3
- #define ENTT_VERSION_MINOR 10
- #define ENTT_VERSION_PATCH 3
- #define ENTT_VERSION \
- ENTT_XSTR(ENTT_VERSION_MAJOR) \
- "." ENTT_XSTR(ENTT_VERSION_MINOR) "." ENTT_XSTR(ENTT_VERSION_PATCH)
- #endif
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #ifndef ENTT_NOEXCEPT
- # define ENTT_NOEXCEPT noexcept
- # define ENTT_NOEXCEPT_IF(expr) noexcept(expr)
- # else
- # define ENTT_NOEXCEPT_IF(...)
- #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
- #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(...) (void(0))
- #elif !defined ENTT_ASSERT
- # include <cassert>
- # define ENTT_ASSERT(condition, ...) assert(condition)
- #endif
- #ifdef ENTT_NO_ETO
- # define ENTT_IGNORE_IF_EMPTY false
- #else
- # define ENTT_IGNORE_IF_EMPTY true
- #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
- #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
- #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 "../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
- #define ENTT_STR(arg) #arg
- #define ENTT_XSTR(arg) ENTT_STR(arg)
- #endif
- #define ENTT_VERSION_MAJOR 3
- #define ENTT_VERSION_MINOR 10
- #define ENTT_VERSION_PATCH 3
- #define ENTT_VERSION \
- ENTT_XSTR(ENTT_VERSION_MAJOR) \
- "." ENTT_XSTR(ENTT_VERSION_MINOR) "." ENTT_XSTR(ENTT_VERSION_PATCH)
- #endif
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #ifndef ENTT_NOEXCEPT
- # define ENTT_NOEXCEPT noexcept
- # define ENTT_NOEXCEPT_IF(expr) noexcept(expr)
- # else
- # define ENTT_NOEXCEPT_IF(...)
- #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
- #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(...) (void(0))
- #elif !defined ENTT_ASSERT
- # include <cassert>
- # define ENTT_ASSERT(condition, ...) assert(condition)
- #endif
- #ifdef ENTT_NO_ETO
- # define ENTT_IGNORE_IF_EMPTY false
- #else
- # define ENTT_IGNORE_IF_EMPTY true
- #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
- #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
- #endif
- // #include "type_traits.hpp"
- #ifndef ENTT_CORE_TYPE_TRAITS_HPP
- #define ENTT_CORE_TYPE_TRAITS_HPP
- #include <cstddef>
- #include <iterator>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- // #include "fwd.hpp"
- #ifndef ENTT_CORE_FWD_HPP
- #define ENTT_CORE_FWD_HPP
- #include <cstdint>
- #include <type_traits>
- // #include "../config/config.h"
- namespace entt {
- template<std::size_t Len = sizeof(double[2]), std::size_t = alignof(typename std::aligned_storage_t<Len + !Len>)>
- 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<>;
- } // 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.
- * @tparam The size of the type if `sizeof` accepts it, 0 otherwise.
- */
- 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))>>
- : 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 Type First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<std::size_t Index, typename Type, typename... Other>
- struct type_list_element<Index, type_list<Type, Other...>>
- : type_list_element<Index - 1u, type_list<Other...>> {};
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam Type First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<typename Type, typename... Other>
- struct type_list_element<0u, type_list<Type, Other...>> {
- /*! @brief Searched type. */
- using type = Type;
- };
- /**
- * @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 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;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename>
- struct type_list_unique;
- /**
- * @brief Removes duplicates types from a type list.
- * @tparam Type One of the types provided by the given type list.
- * @tparam Other The other types provided by the given type list.
- */
- template<typename Type, typename... Other>
- struct type_list_unique<type_list<Type, Other...>> {
- /*! @brief A type list without duplicate types. */
- using type = std::conditional_t<
- (std::is_same_v<Type, Other> || ...),
- typename type_list_unique<type_list<Other...>>::type,
- type_list_cat_t<type_list<Type>, typename type_list_unique<type_list<Other...>>::type>>;
- };
- /*! @brief Removes duplicates types from a type list. */
- template<>
- struct type_list_unique<type_list<>> {
- /*! @brief A type list without duplicate types. */
- using type = type_list<>;
- };
- /**
- * @brief Helper type.
- * @tparam Type A type list.
- */
- template<typename Type>
- using type_list_unique_t = typename type_list_unique<Type>::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::disjunction<std::is_same<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 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 value. */
- static constexpr auto value = Value;
- };
- /**
- * @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 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 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
- * Internal details not to be documented.
- */
- 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
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /*! @copydoc is_iterator */
- template<typename Type>
- struct is_iterator<Type, std::enable_if_t<!std::is_same_v<std::remove_const_t<std::remove_pointer_t<Type>>, void>>>
- : 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::conjunction<std::is_empty<Type>, std::negation<std::is_final<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;
- /**
- * @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, typename = void>
- struct is_equality_comparable: std::false_type {};
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- 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 Type, std::size_t... Index>
- [[nodiscard]] constexpr bool unpack_maybe_equality_comparable(std::index_sequence<Index...>) {
- return (is_equality_comparable<std::tuple_element_t<Index, Type>>::value && ...);
- }
- template<typename>
- [[nodiscard]] constexpr bool maybe_equality_comparable(choice_t<0>) {
- return true;
- }
- template<typename Type>
- [[nodiscard]] constexpr auto maybe_equality_comparable(choice_t<1>) -> decltype(std::declval<typename Type::value_type>(), bool{}) {
- if constexpr(is_iterator_v<Type>) {
- return true;
- } else if constexpr(std::is_same_v<typename Type::value_type, Type>) {
- return maybe_equality_comparable<Type>(choice<0>);
- } else {
- return is_equality_comparable<typename Type::value_type>::value;
- }
- }
- template<typename Type>
- [[nodiscard]] constexpr std::enable_if_t<is_complete_v<std::tuple_size<std::remove_const_t<Type>>>, bool> maybe_equality_comparable(choice_t<2>) {
- if constexpr(has_tuple_size_value<Type>::value) {
- return unpack_maybe_equality_comparable<Type>(std::make_index_sequence<std::tuple_size<Type>::value>{});
- } else {
- return maybe_equality_comparable<Type>(choice<1>);
- }
- }
- } // namespace internal
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /*! @copydoc is_equality_comparable */
- template<typename Type>
- struct is_equality_comparable<Type, std::void_t<decltype(std::declval<Type>() == std::declval<Type>())>>
- : std::bool_constant<internal::maybe_equality_comparable<Type>(choice<2>)> {};
- /**
- * @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 = std::add_const_t<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;
- } // namespace entt
- #endif
- namespace entt {
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- namespace internal {
- template<typename Type, std::size_t, typename = void>
- struct compressed_pair_element {
- using reference = Type &;
- using const_reference = const Type &;
- template<bool Dummy = true, typename = std::enable_if_t<Dummy && std::is_default_constructible_v<Type>>>
- compressed_pair_element()
- : value{} {}
- template<typename Args, typename = std::enable_if_t<!std::is_same_v<std::remove_cv_t<std::remove_reference_t<Args>>, compressed_pair_element>>>
- compressed_pair_element(Args &&args)
- : value{std::forward<Args>(args)} {}
- template<typename... Args, std::size_t... Index>
- compressed_pair_element(std::tuple<Args...> args, std::index_sequence<Index...>)
- : value{std::forward<Args>(std::get<Index>(args))...} {}
- [[nodiscard]] reference get() ENTT_NOEXCEPT {
- return value;
- }
- [[nodiscard]] const_reference get() const ENTT_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<bool Dummy = true, typename = std::enable_if_t<Dummy && std::is_default_constructible_v<base_type>>>
- compressed_pair_element()
- : base_type{} {}
- template<typename Args, typename = std::enable_if_t<!std::is_same_v<std::remove_cv_t<std::remove_reference_t<Args>>, compressed_pair_element>>>
- compressed_pair_element(Args &&args)
- : base_type{std::forward<Args>(args)} {}
- template<typename... Args, std::size_t... Index>
- compressed_pair_element(std::tuple<Args...> args, std::index_sequence<Index...>)
- : base_type{std::forward<Args>(std::get<Index>(args))...} {}
- [[nodiscard]] reference get() ENTT_NOEXCEPT {
- return *this;
- }
- [[nodiscard]] const_reference get() const ENTT_NOEXCEPT {
- return *this;
- }
- };
- } // namespace internal
- /**
- * Internal details not to be documented.
- * @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()
- : 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) = 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)
- : 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)
- : first_base{std::move(args), std::index_sequence_for<Args...>{}},
- second_base{std::move(other), std::index_sequence_for<Other...>{}} {}
- /**
- * @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) = default;
- /**
- * @brief Returns the first element that a pair stores.
- * @return The first element that a pair stores.
- */
- [[nodiscard]] first_type &first() ENTT_NOEXCEPT {
- return static_cast<first_base &>(*this).get();
- }
- /*! @copydoc first */
- [[nodiscard]] const first_type &first() const ENTT_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]] second_type &second() ENTT_NOEXCEPT {
- return static_cast<second_base &>(*this).get();
- }
- /*! @copydoc second */
- [[nodiscard]] const second_type &second() const ENTT_NOEXCEPT {
- return static_cast<const second_base &>(*this).get();
- }
- /**
- * @brief Swaps two compressed pair objects.
- * @param other The compressed pair to swap with.
- */
- void swap(compressed_pair &other) {
- 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>
- decltype(auto) get() ENTT_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>
- decltype(auto) get() const ENTT_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>
- inline void swap(compressed_pair<First, Second> &lhs, compressed_pair<First, Second> &rhs) {
- lhs.swap(rhs);
- }
- } // namespace entt
- // disable structured binding support for clang 6, it messes when specializing tuple_size
- #if !defined __clang_major__ || __clang_major__ > 6
- 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
- #endif
- // #include "../core/iterator.hpp"
- #ifndef ENTT_CORE_ITERATOR_HPP
- #define ENTT_CORE_ITERATOR_HPP
- #include <iterator>
- #include <memory>
- #include <utility>
- // #include "../config/config.h"
- 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 Pointer type. */
- using pointer = Type *;
- /*! @brief Default copy constructor, deleted on purpose. */
- input_iterator_pointer(const input_iterator_pointer &) = delete;
- /*! @brief Default move constructor. */
- input_iterator_pointer(input_iterator_pointer &&) = default;
- /**
- * @brief Constructs a proxy object by move.
- * @param val Value to use to initialize the proxy object.
- */
- input_iterator_pointer(Type &&val)
- : value{std::move(val)} {}
- /**
- * @brief Default copy assignment operator, deleted on purpose.
- * @return This proxy object.
- */
- input_iterator_pointer &operator=(const input_iterator_pointer &) = delete;
- /**
- * @brief Default move assignment operator.
- * @return This proxy object.
- */
- input_iterator_pointer &operator=(input_iterator_pointer &&) = default;
- /**
- * @brief Access operator for accessing wrapped values.
- * @return A pointer to the wrapped value.
- */
- [[nodiscard]] pointer operator->() ENTT_NOEXCEPT {
- return std::addressof(value);
- }
- private:
- Type value;
- };
- /**
- * @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. */
- iterable_adaptor() = default;
- /**
- * @brief Creates an iterable object from a pair of iterators.
- * @param from Begin iterator.
- * @param to End iterator.
- */
- iterable_adaptor(iterator from, sentinel to)
- : first{from},
- last{to} {}
- /**
- * @brief Returns an iterator to the beginning.
- * @return An iterator to the first element of the range.
- */
- [[nodiscard]] iterator begin() const ENTT_NOEXCEPT {
- return first;
- }
- /**
- * @brief Returns an iterator to the end.
- * @return An iterator to the element following the last element of the
- * range.
- */
- [[nodiscard]] sentinel end() const ENTT_NOEXCEPT {
- return last;
- }
- /*! @copydoc begin */
- [[nodiscard]] iterator cbegin() const ENTT_NOEXCEPT {
- return begin();
- }
- /*! @copydoc end */
- [[nodiscard]] sentinel cend() const ENTT_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 <limits>
- #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) ENTT_NOEXCEPT {
- if constexpr(std::is_pointer_v<std::remove_cv_t<std::remove_reference_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) ENTT_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) ENTT_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) ENTT_NOEXCEPT {
- ENTT_ASSERT(std::allocator_traits<Allocator>::propagate_on_container_swap::value || lhs == rhs, "Cannot swap the containers");
- if constexpr(std::allocator_traits<Allocator>::propagate_on_container_swap::value) {
- using std::swap;
- swap(lhs, rhs);
- }
- }
- /**
- * @brief Checks whether a value is a power of two or not.
- * @param value A value that may or may not be a power of two.
- * @return True if the value is a power of two, false otherwise.
- */
- [[nodiscard]] inline constexpr bool is_power_of_two(const std::size_t value) ENTT_NOEXCEPT {
- return value && ((value & (value - 1)) == 0);
- }
- /**
- * @brief Computes the smallest power of two greater than or equal to a value.
- * @param value The value to use.
- * @return The smallest power of two greater than or equal to the given value.
- */
- [[nodiscard]] inline constexpr std::size_t next_power_of_two(const std::size_t value) ENTT_NOEXCEPT {
- ENTT_ASSERT(value < (std::size_t{1u} << (std::numeric_limits<std::size_t>::digits - 1)), "Numeric limits exceeded");
- std::size_t curr = value - (value != 0u);
- for(int next = 1; next < std::numeric_limits<std::size_t>::digits; next = next * 2) {
- curr |= curr >> next;
- }
- return ++curr;
- }
- /**
- * @brief Fast module utility function (powers of two only).
- * @param value A value for which to calculate the modulus.
- * @param mod _Modulus_, it must be a power of two.
- * @return The common remainder.
- */
- [[nodiscard]] inline constexpr std::size_t fast_mod(const std::size_t value, const std::size_t mod) ENTT_NOEXCEPT {
- ENTT_ASSERT(is_power_of_two(mod), "Value must be a power of two");
- return value & (mod - 1u);
- }
- /**
- * @brief Deleter for allocator-aware unique pointers (waiting for C++20).
- * @tparam Args Types of arguments to use to construct the object.
- */
- 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.
- */
- allocation_deleter(const allocator_type &alloc)
- : Allocator{alloc} {}
- /**
- * @brief Destroys the pointed object and deallocates its memory.
- * @param ptr A valid pointer to an object of the given type.
- */
- void operator()(pointer ptr) {
- using alloc_traits = typename 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>
- 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
- * Internal details not to be documented.
- */
- 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) ENTT_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) ENTT_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) ENTT_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) ENTT_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) ENTT_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) ENTT_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
- /**
- * Internal details not to be documented.
- * @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) ENTT_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([&](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 <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.
- * @tparam The size of the type if `sizeof` accepts it, 0 otherwise.
- */
- 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))>>
- : 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 Type First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<std::size_t Index, typename Type, typename... Other>
- struct type_list_element<Index, type_list<Type, Other...>>
- : type_list_element<Index - 1u, type_list<Other...>> {};
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam Type First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<typename Type, typename... Other>
- struct type_list_element<0u, type_list<Type, Other...>> {
- /*! @brief Searched type. */
- using type = Type;
- };
- /**
- * @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 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;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename>
- struct type_list_unique;
- /**
- * @brief Removes duplicates types from a type list.
- * @tparam Type One of the types provided by the given type list.
- * @tparam Other The other types provided by the given type list.
- */
- template<typename Type, typename... Other>
- struct type_list_unique<type_list<Type, Other...>> {
- /*! @brief A type list without duplicate types. */
- using type = std::conditional_t<
- (std::is_same_v<Type, Other> || ...),
- typename type_list_unique<type_list<Other...>>::type,
- type_list_cat_t<type_list<Type>, typename type_list_unique<type_list<Other...>>::type>>;
- };
- /*! @brief Removes duplicates types from a type list. */
- template<>
- struct type_list_unique<type_list<>> {
- /*! @brief A type list without duplicate types. */
- using type = type_list<>;
- };
- /**
- * @brief Helper type.
- * @tparam Type A type list.
- */
- template<typename Type>
- using type_list_unique_t = typename type_list_unique<Type>::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::disjunction<std::is_same<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 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 value. */
- static constexpr auto value = Value;
- };
- /**
- * @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 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 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
- * Internal details not to be documented.
- */
- 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
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /*! @copydoc is_iterator */
- template<typename Type>
- struct is_iterator<Type, std::enable_if_t<!std::is_same_v<std::remove_const_t<std::remove_pointer_t<Type>>, void>>>
- : 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::conjunction<std::is_empty<Type>, std::negation<std::is_final<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;
- /**
- * @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, typename = void>
- struct is_equality_comparable: std::false_type {};
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- 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 Type, std::size_t... Index>
- [[nodiscard]] constexpr bool unpack_maybe_equality_comparable(std::index_sequence<Index...>) {
- return (is_equality_comparable<std::tuple_element_t<Index, Type>>::value && ...);
- }
- template<typename>
- [[nodiscard]] constexpr bool maybe_equality_comparable(choice_t<0>) {
- return true;
- }
- template<typename Type>
- [[nodiscard]] constexpr auto maybe_equality_comparable(choice_t<1>) -> decltype(std::declval<typename Type::value_type>(), bool{}) {
- if constexpr(is_iterator_v<Type>) {
- return true;
- } else if constexpr(std::is_same_v<typename Type::value_type, Type>) {
- return maybe_equality_comparable<Type>(choice<0>);
- } else {
- return is_equality_comparable<typename Type::value_type>::value;
- }
- }
- template<typename Type>
- [[nodiscard]] constexpr std::enable_if_t<is_complete_v<std::tuple_size<std::remove_const_t<Type>>>, bool> maybe_equality_comparable(choice_t<2>) {
- if constexpr(has_tuple_size_value<Type>::value) {
- return unpack_maybe_equality_comparable<Type>(std::make_index_sequence<std::tuple_size<Type>::value>{});
- } else {
- return maybe_equality_comparable<Type>(choice<1>);
- }
- }
- } // namespace internal
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /*! @copydoc is_equality_comparable */
- template<typename Type>
- struct is_equality_comparable<Type, std::void_t<decltype(std::declval<Type>() == std::declval<Type>())>>
- : std::bool_constant<internal::maybe_equality_comparable<Type>(choice<2>)> {};
- /**
- * @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 = std::add_const_t<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;
- } // namespace entt
- #endif
- // #include "fwd.hpp"
- #ifndef ENTT_CONTAINER_FWD_HPP
- #define ENTT_CONTAINER_FWD_HPP
- #include <functional>
- #include <memory>
- namespace entt {
- template<
- typename Key,
- typename Type,
- typename = std::hash<Key>,
- typename = std::equal_to<Key>,
- typename = std::allocator<std::pair<const Key, Type>>>
- class dense_map;
- template<
- typename Type,
- typename = std::hash<Type>,
- typename = std::equal_to<Type>,
- typename = std::allocator<Type>>
- class dense_set;
- } // namespace entt
- #endif
- namespace entt {
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- namespace internal {
- 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;
- dense_map_iterator() ENTT_NOEXCEPT
- : it{} {}
- dense_map_iterator(const It iter) ENTT_NOEXCEPT
- : it{iter} {}
- template<typename Other, typename = std::enable_if_t<!std::is_same_v<It, Other> && std::is_constructible_v<It, Other>>>
- dense_map_iterator(const dense_map_iterator<Other> &other) ENTT_NOEXCEPT
- : it{other.it} {}
- dense_map_iterator &operator++() ENTT_NOEXCEPT {
- return ++it, *this;
- }
- dense_map_iterator operator++(int) ENTT_NOEXCEPT {
- dense_map_iterator orig = *this;
- return ++(*this), orig;
- }
- dense_map_iterator &operator--() ENTT_NOEXCEPT {
- return --it, *this;
- }
- dense_map_iterator operator--(int) ENTT_NOEXCEPT {
- dense_map_iterator orig = *this;
- return operator--(), orig;
- }
- dense_map_iterator &operator+=(const difference_type value) ENTT_NOEXCEPT {
- it += value;
- return *this;
- }
- dense_map_iterator operator+(const difference_type value) const ENTT_NOEXCEPT {
- dense_map_iterator copy = *this;
- return (copy += value);
- }
- dense_map_iterator &operator-=(const difference_type value) ENTT_NOEXCEPT {
- return (*this += -value);
- }
- dense_map_iterator operator-(const difference_type value) const ENTT_NOEXCEPT {
- return (*this + -value);
- }
- [[nodiscard]] reference operator[](const difference_type value) const ENTT_NOEXCEPT {
- return {it[value].element.first, it[value].element.second};
- }
- [[nodiscard]] pointer operator->() const ENTT_NOEXCEPT {
- return operator*();
- }
- [[nodiscard]] reference operator*() const ENTT_NOEXCEPT {
- return {it->element.first, it->element.second};
- }
- template<typename ILhs, typename IRhs>
- friend std::ptrdiff_t operator-(const dense_map_iterator<ILhs> &, const dense_map_iterator<IRhs> &) ENTT_NOEXCEPT;
- template<typename ILhs, typename IRhs>
- friend bool operator==(const dense_map_iterator<ILhs> &, const dense_map_iterator<IRhs> &) ENTT_NOEXCEPT;
- template<typename ILhs, typename IRhs>
- friend bool operator<(const dense_map_iterator<ILhs> &, const dense_map_iterator<IRhs> &) ENTT_NOEXCEPT;
- private:
- It it;
- };
- template<typename ILhs, typename IRhs>
- [[nodiscard]] std::ptrdiff_t operator-(const dense_map_iterator<ILhs> &lhs, const dense_map_iterator<IRhs> &rhs) ENTT_NOEXCEPT {
- return lhs.it - rhs.it;
- }
- template<typename ILhs, typename IRhs>
- [[nodiscard]] bool operator==(const dense_map_iterator<ILhs> &lhs, const dense_map_iterator<IRhs> &rhs) ENTT_NOEXCEPT {
- return lhs.it == rhs.it;
- }
- template<typename ILhs, typename IRhs>
- [[nodiscard]] bool operator!=(const dense_map_iterator<ILhs> &lhs, const dense_map_iterator<IRhs> &rhs) ENTT_NOEXCEPT {
- return !(lhs == rhs);
- }
- template<typename ILhs, typename IRhs>
- [[nodiscard]] bool operator<(const dense_map_iterator<ILhs> &lhs, const dense_map_iterator<IRhs> &rhs) ENTT_NOEXCEPT {
- return lhs.it < rhs.it;
- }
- template<typename ILhs, typename IRhs>
- [[nodiscard]] bool operator>(const dense_map_iterator<ILhs> &lhs, const dense_map_iterator<IRhs> &rhs) ENTT_NOEXCEPT {
- return rhs < lhs;
- }
- template<typename ILhs, typename IRhs>
- [[nodiscard]] bool operator<=(const dense_map_iterator<ILhs> &lhs, const dense_map_iterator<IRhs> &rhs) ENTT_NOEXCEPT {
- return !(lhs > rhs);
- }
- template<typename ILhs, typename IRhs>
- [[nodiscard]] bool operator>=(const dense_map_iterator<ILhs> &lhs, const dense_map_iterator<IRhs> &rhs) ENTT_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;
- dense_map_local_iterator() ENTT_NOEXCEPT
- : it{},
- offset{} {}
- dense_map_local_iterator(It iter, const std::size_t pos) ENTT_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>>>
- dense_map_local_iterator(const dense_map_local_iterator<Other> &other) ENTT_NOEXCEPT
- : it{other.it},
- offset{other.offset} {}
- dense_map_local_iterator &operator++() ENTT_NOEXCEPT {
- return offset = it[offset].next, *this;
- }
- dense_map_local_iterator operator++(int) ENTT_NOEXCEPT {
- dense_map_local_iterator orig = *this;
- return ++(*this), orig;
- }
- [[nodiscard]] pointer operator->() const ENTT_NOEXCEPT {
- return operator*();
- }
- [[nodiscard]] reference operator*() const ENTT_NOEXCEPT {
- return {it[offset].element.first, it[offset].element.second};
- }
- [[nodiscard]] std::size_t index() const ENTT_NOEXCEPT {
- return offset;
- }
- private:
- It it;
- std::size_t offset;
- };
- template<typename ILhs, typename IRhs>
- [[nodiscard]] bool operator==(const dense_map_local_iterator<ILhs> &lhs, const dense_map_local_iterator<IRhs> &rhs) ENTT_NOEXCEPT {
- return lhs.index() == rhs.index();
- }
- template<typename ILhs, typename IRhs>
- [[nodiscard]] bool operator!=(const dense_map_local_iterator<ILhs> &lhs, const dense_map_local_iterator<IRhs> &rhs) ENTT_NOEXCEPT {
- return !(lhs == rhs);
- }
- } // namespace internal
- /**
- * Internal details not to be documented.
- * @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;
- using node_type = internal::dense_map_node<Key, Type>;
- using alloc_traits = typename 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 ENTT_NOEXCEPT {
- return fast_mod(sparse.second()(key), bucket_count());
- }
- template<typename Other>
- [[nodiscard]] auto constrained_find(const Other &key, std::size_t bucket) {
- for(auto it = begin(bucket), last = end(bucket); it != last; ++it) {
- if(packed.second()(it->first, key)) {
- return begin() + static_cast<typename iterator::difference_type>(it.index());
- }
- }
- return end();
- }
- template<typename Other>
- [[nodiscard]] auto constrained_find(const Other &key, std::size_t bucket) const {
- for(auto it = cbegin(bucket), last = cend(bucket); it != last; ++it) {
- if(packed.second()(it->first, key)) {
- return cbegin() + static_cast<typename iterator::difference_type>(it.index());
- }
- }
- 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) {
- packed.first()[pos] = std::move(packed.first().back());
- size_type *curr = sparse.first().data() + key_to_bucket(packed.first().back().element.first);
- for(; *curr != last; curr = &packed.first()[*curr].next) {}
- *curr = pos;
- }
- packed.first().pop_back();
- }
- void rehash_if_required() {
- if(size() > (bucket_count() * max_load_factor())) {
- rehash(bucket_count() * 2u);
- }
- }
- public:
- /*! @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 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 Allocator type. */
- using allocator_type = Allocator;
- /*! @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 bucket_count Minimal number of buckets.
- * @param allocator The allocator to use.
- */
- dense_map(const size_type bucket_count, const allocator_type &allocator)
- : dense_map{bucket_count, hasher{}, key_equal{}, allocator} {}
- /**
- * @brief Constructs an empty container with a given allocator, hash
- * function and user supplied minimal number of buckets.
- * @param bucket_count Minimal number of buckets.
- * @param hash Hash function to use.
- * @param allocator The allocator to use.
- */
- dense_map(const size_type bucket_count, const hasher &hash, const allocator_type &allocator)
- : dense_map{bucket_count, 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 bucket_count 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 bucket_count, const hasher &hash = hasher{}, const key_equal &equal = key_equal{}, const allocator_type &allocator = allocator_type{})
- : sparse{allocator, hash},
- packed{allocator, equal},
- threshold{default_threshold} {
- rehash(bucket_count);
- }
- /*! @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 &&) = 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 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 &&) = default;
- /**
- * @brief Returns the associated allocator.
- * @return The associated allocator.
- */
- [[nodiscard]] constexpr allocator_type get_allocator() const ENTT_NOEXCEPT {
- return sparse.first().get_allocator();
- }
- /**
- * @brief Returns an iterator to the beginning.
- *
- * The returned iterator points to the first instance of the internal array.
- * 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 ENTT_NOEXCEPT {
- return packed.first().begin();
- }
- /*! @copydoc cbegin */
- [[nodiscard]] const_iterator begin() const ENTT_NOEXCEPT {
- return cbegin();
- }
- /*! @copydoc begin */
- [[nodiscard]] iterator begin() ENTT_NOEXCEPT {
- return packed.first().begin();
- }
- /**
- * @brief Returns an iterator to the end.
- *
- * The returned iterator points to the element following the last instance
- * of the internal array. Attempting to dereference the returned iterator
- * results in undefined behavior.
- *
- * @return An iterator to the element following the last instance of the
- * internal array.
- */
- [[nodiscard]] const_iterator cend() const ENTT_NOEXCEPT {
- return packed.first().end();
- }
- /*! @copydoc cend */
- [[nodiscard]] const_iterator end() const ENTT_NOEXCEPT {
- return cend();
- }
- /*! @copydoc end */
- [[nodiscard]] iterator end() ENTT_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 ENTT_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 ENTT_NOEXCEPT {
- return packed.first().size();
- }
- /*! @brief Clears the container. */
- void clear() ENTT_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()[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().data() + key_to_bucket(key); *curr != (std::numeric_limits<size_type>::max)(); 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 Exchanges the contents with those of a given container.
- * @param other Container to exchange the content with.
- */
- void swap(dense_map &other) {
- using std::swap;
- swap(sparse, other.sparse);
- swap(packed, other.packed);
- swap(threshold, other.threshold);
- }
- /**
- * @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 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 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
- * 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 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 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 {packed.first().begin(), (std::numeric_limits<size_type>::max)()};
- }
- /**
- * @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([[maybe_unused]] 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 {packed.first().begin(), (std::numeric_limits<size_type>::max)()};
- }
- /**
- * @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 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 count New number of buckets.
- */
- void rehash(const size_type count) {
- auto value = (std::max)(count, minimum_capacity);
- value = (std::max)(value, static_cast<size_type>(size() / max_load_factor()));
- if(const auto sz = next_power_of_two(value); sz != bucket_count()) {
- sparse.first().resize(sz);
- std::fill(sparse.first().begin(), sparse.first().end(), (std::numeric_limits<size_type>::max)());
- 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 count New number of elements.
- */
- void reserve(const size_type count) {
- packed.first().reserve(count);
- rehash(static_cast<size_type>(std::ceil(count / 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;
- };
- } // namespace entt
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- 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
- /**
- * Internal details not to be documented.
- * @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 "../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
- #define ENTT_STR(arg) #arg
- #define ENTT_XSTR(arg) ENTT_STR(arg)
- #endif
- #define ENTT_VERSION_MAJOR 3
- #define ENTT_VERSION_MINOR 10
- #define ENTT_VERSION_PATCH 3
- #define ENTT_VERSION \
- ENTT_XSTR(ENTT_VERSION_MAJOR) \
- "." ENTT_XSTR(ENTT_VERSION_MINOR) "." ENTT_XSTR(ENTT_VERSION_PATCH)
- #endif
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #ifndef ENTT_NOEXCEPT
- # define ENTT_NOEXCEPT noexcept
- # define ENTT_NOEXCEPT_IF(expr) noexcept(expr)
- # else
- # define ENTT_NOEXCEPT_IF(...)
- #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
- #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(...) (void(0))
- #elif !defined ENTT_ASSERT
- # include <cassert>
- # define ENTT_ASSERT(condition, ...) assert(condition)
- #endif
- #ifdef ENTT_NO_ETO
- # define ENTT_IGNORE_IF_EMPTY false
- #else
- # define ENTT_IGNORE_IF_EMPTY true
- #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
- #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
- #endif
- // #include "type_traits.hpp"
- #ifndef ENTT_CORE_TYPE_TRAITS_HPP
- #define ENTT_CORE_TYPE_TRAITS_HPP
- #include <cstddef>
- #include <iterator>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- // #include "fwd.hpp"
- #ifndef ENTT_CORE_FWD_HPP
- #define ENTT_CORE_FWD_HPP
- #include <cstdint>
- #include <type_traits>
- // #include "../config/config.h"
- namespace entt {
- template<std::size_t Len = sizeof(double[2]), std::size_t = alignof(typename std::aligned_storage_t<Len + !Len>)>
- 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<>;
- } // 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.
- * @tparam The size of the type if `sizeof` accepts it, 0 otherwise.
- */
- 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))>>
- : 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 Type First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<std::size_t Index, typename Type, typename... Other>
- struct type_list_element<Index, type_list<Type, Other...>>
- : type_list_element<Index - 1u, type_list<Other...>> {};
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam Type First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<typename Type, typename... Other>
- struct type_list_element<0u, type_list<Type, Other...>> {
- /*! @brief Searched type. */
- using type = Type;
- };
- /**
- * @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 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;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename>
- struct type_list_unique;
- /**
- * @brief Removes duplicates types from a type list.
- * @tparam Type One of the types provided by the given type list.
- * @tparam Other The other types provided by the given type list.
- */
- template<typename Type, typename... Other>
- struct type_list_unique<type_list<Type, Other...>> {
- /*! @brief A type list without duplicate types. */
- using type = std::conditional_t<
- (std::is_same_v<Type, Other> || ...),
- typename type_list_unique<type_list<Other...>>::type,
- type_list_cat_t<type_list<Type>, typename type_list_unique<type_list<Other...>>::type>>;
- };
- /*! @brief Removes duplicates types from a type list. */
- template<>
- struct type_list_unique<type_list<>> {
- /*! @brief A type list without duplicate types. */
- using type = type_list<>;
- };
- /**
- * @brief Helper type.
- * @tparam Type A type list.
- */
- template<typename Type>
- using type_list_unique_t = typename type_list_unique<Type>::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::disjunction<std::is_same<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 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 value. */
- static constexpr auto value = Value;
- };
- /**
- * @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 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 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
- * Internal details not to be documented.
- */
- 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
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /*! @copydoc is_iterator */
- template<typename Type>
- struct is_iterator<Type, std::enable_if_t<!std::is_same_v<std::remove_const_t<std::remove_pointer_t<Type>>, void>>>
- : 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::conjunction<std::is_empty<Type>, std::negation<std::is_final<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;
- /**
- * @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, typename = void>
- struct is_equality_comparable: std::false_type {};
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- 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 Type, std::size_t... Index>
- [[nodiscard]] constexpr bool unpack_maybe_equality_comparable(std::index_sequence<Index...>) {
- return (is_equality_comparable<std::tuple_element_t<Index, Type>>::value && ...);
- }
- template<typename>
- [[nodiscard]] constexpr bool maybe_equality_comparable(choice_t<0>) {
- return true;
- }
- template<typename Type>
- [[nodiscard]] constexpr auto maybe_equality_comparable(choice_t<1>) -> decltype(std::declval<typename Type::value_type>(), bool{}) {
- if constexpr(is_iterator_v<Type>) {
- return true;
- } else if constexpr(std::is_same_v<typename Type::value_type, Type>) {
- return maybe_equality_comparable<Type>(choice<0>);
- } else {
- return is_equality_comparable<typename Type::value_type>::value;
- }
- }
- template<typename Type>
- [[nodiscard]] constexpr std::enable_if_t<is_complete_v<std::tuple_size<std::remove_const_t<Type>>>, bool> maybe_equality_comparable(choice_t<2>) {
- if constexpr(has_tuple_size_value<Type>::value) {
- return unpack_maybe_equality_comparable<Type>(std::make_index_sequence<std::tuple_size<Type>::value>{});
- } else {
- return maybe_equality_comparable<Type>(choice<1>);
- }
- }
- } // namespace internal
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /*! @copydoc is_equality_comparable */
- template<typename Type>
- struct is_equality_comparable<Type, std::void_t<decltype(std::declval<Type>() == std::declval<Type>())>>
- : std::bool_constant<internal::maybe_equality_comparable<Type>(choice<2>)> {};
- /**
- * @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 = std::add_const_t<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;
- } // namespace entt
- #endif
- namespace entt {
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- namespace internal {
- template<typename Type, std::size_t, typename = void>
- struct compressed_pair_element {
- using reference = Type &;
- using const_reference = const Type &;
- template<bool Dummy = true, typename = std::enable_if_t<Dummy && std::is_default_constructible_v<Type>>>
- compressed_pair_element()
- : value{} {}
- template<typename Args, typename = std::enable_if_t<!std::is_same_v<std::remove_cv_t<std::remove_reference_t<Args>>, compressed_pair_element>>>
- compressed_pair_element(Args &&args)
- : value{std::forward<Args>(args)} {}
- template<typename... Args, std::size_t... Index>
- compressed_pair_element(std::tuple<Args...> args, std::index_sequence<Index...>)
- : value{std::forward<Args>(std::get<Index>(args))...} {}
- [[nodiscard]] reference get() ENTT_NOEXCEPT {
- return value;
- }
- [[nodiscard]] const_reference get() const ENTT_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<bool Dummy = true, typename = std::enable_if_t<Dummy && std::is_default_constructible_v<base_type>>>
- compressed_pair_element()
- : base_type{} {}
- template<typename Args, typename = std::enable_if_t<!std::is_same_v<std::remove_cv_t<std::remove_reference_t<Args>>, compressed_pair_element>>>
- compressed_pair_element(Args &&args)
- : base_type{std::forward<Args>(args)} {}
- template<typename... Args, std::size_t... Index>
- compressed_pair_element(std::tuple<Args...> args, std::index_sequence<Index...>)
- : base_type{std::forward<Args>(std::get<Index>(args))...} {}
- [[nodiscard]] reference get() ENTT_NOEXCEPT {
- return *this;
- }
- [[nodiscard]] const_reference get() const ENTT_NOEXCEPT {
- return *this;
- }
- };
- } // namespace internal
- /**
- * Internal details not to be documented.
- * @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()
- : 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) = 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)
- : 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)
- : first_base{std::move(args), std::index_sequence_for<Args...>{}},
- second_base{std::move(other), std::index_sequence_for<Other...>{}} {}
- /**
- * @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) = default;
- /**
- * @brief Returns the first element that a pair stores.
- * @return The first element that a pair stores.
- */
- [[nodiscard]] first_type &first() ENTT_NOEXCEPT {
- return static_cast<first_base &>(*this).get();
- }
- /*! @copydoc first */
- [[nodiscard]] const first_type &first() const ENTT_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]] second_type &second() ENTT_NOEXCEPT {
- return static_cast<second_base &>(*this).get();
- }
- /*! @copydoc second */
- [[nodiscard]] const second_type &second() const ENTT_NOEXCEPT {
- return static_cast<const second_base &>(*this).get();
- }
- /**
- * @brief Swaps two compressed pair objects.
- * @param other The compressed pair to swap with.
- */
- void swap(compressed_pair &other) {
- 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>
- decltype(auto) get() ENTT_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>
- decltype(auto) get() const ENTT_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>
- inline void swap(compressed_pair<First, Second> &lhs, compressed_pair<First, Second> &rhs) {
- lhs.swap(rhs);
- }
- } // namespace entt
- // disable structured binding support for clang 6, it messes when specializing tuple_size
- #if !defined __clang_major__ || __clang_major__ > 6
- 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
- #endif
- // #include "../core/fwd.hpp"
- #ifndef ENTT_CORE_FWD_HPP
- #define ENTT_CORE_FWD_HPP
- #include <cstdint>
- #include <type_traits>
- // #include "../config/config.h"
- namespace entt {
- template<std::size_t Len = sizeof(double[2]), std::size_t = alignof(typename std::aligned_storage_t<Len + !Len>)>
- 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<>;
- } // namespace entt
- #endif
- // #include "../core/iterator.hpp"
- #ifndef ENTT_CORE_ITERATOR_HPP
- #define ENTT_CORE_ITERATOR_HPP
- #include <iterator>
- #include <memory>
- #include <utility>
- // #include "../config/config.h"
- 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 Pointer type. */
- using pointer = Type *;
- /*! @brief Default copy constructor, deleted on purpose. */
- input_iterator_pointer(const input_iterator_pointer &) = delete;
- /*! @brief Default move constructor. */
- input_iterator_pointer(input_iterator_pointer &&) = default;
- /**
- * @brief Constructs a proxy object by move.
- * @param val Value to use to initialize the proxy object.
- */
- input_iterator_pointer(Type &&val)
- : value{std::move(val)} {}
- /**
- * @brief Default copy assignment operator, deleted on purpose.
- * @return This proxy object.
- */
- input_iterator_pointer &operator=(const input_iterator_pointer &) = delete;
- /**
- * @brief Default move assignment operator.
- * @return This proxy object.
- */
- input_iterator_pointer &operator=(input_iterator_pointer &&) = default;
- /**
- * @brief Access operator for accessing wrapped values.
- * @return A pointer to the wrapped value.
- */
- [[nodiscard]] pointer operator->() ENTT_NOEXCEPT {
- return std::addressof(value);
- }
- private:
- Type value;
- };
- /**
- * @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. */
- iterable_adaptor() = default;
- /**
- * @brief Creates an iterable object from a pair of iterators.
- * @param from Begin iterator.
- * @param to End iterator.
- */
- iterable_adaptor(iterator from, sentinel to)
- : first{from},
- last{to} {}
- /**
- * @brief Returns an iterator to the beginning.
- * @return An iterator to the first element of the range.
- */
- [[nodiscard]] iterator begin() const ENTT_NOEXCEPT {
- return first;
- }
- /**
- * @brief Returns an iterator to the end.
- * @return An iterator to the element following the last element of the
- * range.
- */
- [[nodiscard]] sentinel end() const ENTT_NOEXCEPT {
- return last;
- }
- /*! @copydoc begin */
- [[nodiscard]] iterator cbegin() const ENTT_NOEXCEPT {
- return begin();
- }
- /*! @copydoc end */
- [[nodiscard]] sentinel cend() const ENTT_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 <utility>
- // #include "../config/config.h"
- 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<class Type>
- [[nodiscard]] constexpr Type &&operator()(Type &&value) const ENTT_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) ENTT_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) ENTT_NOEXCEPT {
- return func;
- }
- /**
- * @brief Helper type for visitors.
- * @tparam Func Types of function objects.
- */
- template<class... Func>
- struct overloaded: Func... {
- using Func::operator()...;
- };
- /**
- * @brief Deduction guide.
- * @tparam Func Types of function objects.
- */
- template<class... Func>
- overloaded(Func...) -> overloaded<Func...>;
- /**
- * @brief Basic implementation of a y-combinator.
- * @tparam Func Type of a potentially recursive function.
- */
- template<class Func>
- struct y_combinator {
- /**
- * @brief Constructs a y-combinator from a given function.
- * @param recursive A potentially recursive function.
- */
- y_combinator(Func recursive)
- : 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<class... Args>
- decltype(auto) operator()(Args &&...args) const {
- return func(*this, std::forward<Args>(args)...);
- }
- /*! @copydoc operator()() */
- template<class... Args>
- decltype(auto) operator()(Args &&...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 "../config/config.h"
- // #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 {
- /*! @brief Resource handles are friends with each other. */
- template<typename>
- friend class resource;
- template<typename Other>
- static constexpr bool is_acceptable_v = !std::is_same_v<Type, Other> && std::is_constructible_v<Type &, Other &>;
- public:
- /*! @brief Default constructor. */
- resource() ENTT_NOEXCEPT
- : value{} {}
- /**
- * @brief Creates a handle from a weak pointer, namely a resource.
- * @param res A weak pointer to a resource.
- */
- explicit resource(std::shared_ptr<Type> res) ENTT_NOEXCEPT
- : value{std::move(res)} {}
- /*! @brief Default copy constructor. */
- resource(const resource &) ENTT_NOEXCEPT = default;
- /*! @brief Default move constructor. */
- resource(resource &&) ENTT_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, Type &res) ENTT_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_v<Other>>>
- resource(const resource<Other> &other) ENTT_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_v<Other>>>
- resource(resource<Other> &&other) ENTT_NOEXCEPT
- : value{std::move(other.value)} {}
- /**
- * @brief Default copy assignment operator.
- * @return This resource handle.
- */
- resource &operator=(const resource &) ENTT_NOEXCEPT = default;
- /**
- * @brief Default move assignment operator.
- * @return This resource handle.
- */
- resource &operator=(resource &&) ENTT_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>
- std::enable_if_t<is_acceptable_v<Other>, resource &>
- operator=(const resource<Other> &other) ENTT_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>
- std::enable_if_t<is_acceptable_v<Other>, resource &>
- operator=(resource<Other> &&other) ENTT_NOEXCEPT {
- value = std::move(other.value);
- return *this;
- }
- /**
- * @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]] Type &operator*() const ENTT_NOEXCEPT {
- return *value;
- }
- /*! @copydoc operator* */
- [[nodiscard]] operator Type &() const ENTT_NOEXCEPT {
- return *value;
- }
- /**
- * @brief Returns a pointer to the managed resource.
- * @return A pointer to the managed resource.
- */
- [[nodiscard]] Type *operator->() const ENTT_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 ENTT_NOEXCEPT {
- return static_cast<bool>(value);
- }
- /**
- * @brief Returns the number of handles pointing the same resource.
- * @return The number of handles pointing the same resource.
- */
- [[nodiscard]] long use_count() const ENTT_NOEXCEPT {
- return value.use_count();
- }
- private:
- std::shared_ptr<Type> value;
- };
- /**
- * @brief Compares two handles.
- * @tparam Res Type of resource managed by the first handle.
- * @tparam Other 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 Res, typename Other>
- [[nodiscard]] bool operator==(const resource<Res> &lhs, const resource<Other> &rhs) ENTT_NOEXCEPT {
- return (std::addressof(*lhs) == std::addressof(*rhs));
- }
- /**
- * @brief Compares two handles.
- * @tparam Res Type of resource managed by the first handle.
- * @tparam Other 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 registry, true otherwise.
- */
- template<typename Res, typename Other>
- [[nodiscard]] bool operator!=(const resource<Res> &lhs, const resource<Other> &rhs) ENTT_NOEXCEPT {
- return !(lhs == rhs);
- }
- /**
- * @brief Compares two handles.
- * @tparam Res Type of resource managed by the first handle.
- * @tparam Other 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 Res, typename Other>
- [[nodiscard]] bool operator<(const resource<Res> &lhs, const resource<Other> &rhs) ENTT_NOEXCEPT {
- return (std::addressof(*lhs) < std::addressof(*rhs));
- }
- /**
- * @brief Compares two handles.
- * @tparam Res Type of resource managed by the first handle.
- * @tparam Other 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 Res, typename Other>
- [[nodiscard]] bool operator>(const resource<Res> &lhs, const resource<Other> &rhs) ENTT_NOEXCEPT {
- return (std::addressof(*lhs) > std::addressof(*rhs));
- }
- /**
- * @brief Compares two handles.
- * @tparam Res Type of resource managed by the first handle.
- * @tparam Other 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 Res, typename Other>
- [[nodiscard]] bool operator<=(const resource<Res> &lhs, const resource<Other> &rhs) ENTT_NOEXCEPT {
- return !(lhs > rhs);
- }
- /**
- * @brief Compares two handles.
- * @tparam Res Type of resource managed by the first handle.
- * @tparam Other 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 Res, typename Other>
- [[nodiscard]] bool operator>=(const resource<Res> &lhs, const resource<Other> &rhs) ENTT_NOEXCEPT {
- return !(lhs < rhs);
- }
- } // namespace entt
- #endif
- namespace entt {
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- 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;
- resource_cache_iterator() ENTT_NOEXCEPT = default;
- resource_cache_iterator(const It iter) ENTT_NOEXCEPT
- : it{iter} {}
- template<typename Other, typename = std::enable_if_t<!std::is_same_v<It, Other> && std::is_constructible_v<It, Other>>>
- resource_cache_iterator(const resource_cache_iterator<std::remove_const_t<Type>, Other> &other) ENTT_NOEXCEPT
- : it{other.it} {}
- resource_cache_iterator &operator++() ENTT_NOEXCEPT {
- return ++it, *this;
- }
- resource_cache_iterator operator++(int) ENTT_NOEXCEPT {
- resource_cache_iterator orig = *this;
- return ++(*this), orig;
- }
- resource_cache_iterator &operator--() ENTT_NOEXCEPT {
- return --it, *this;
- }
- resource_cache_iterator operator--(int) ENTT_NOEXCEPT {
- resource_cache_iterator orig = *this;
- return operator--(), orig;
- }
- resource_cache_iterator &operator+=(const difference_type value) ENTT_NOEXCEPT {
- it += value;
- return *this;
- }
- resource_cache_iterator operator+(const difference_type value) const ENTT_NOEXCEPT {
- resource_cache_iterator copy = *this;
- return (copy += value);
- }
- resource_cache_iterator &operator-=(const difference_type value) ENTT_NOEXCEPT {
- return (*this += -value);
- }
- resource_cache_iterator operator-(const difference_type value) const ENTT_NOEXCEPT {
- return (*this + -value);
- }
- [[nodiscard]] reference operator[](const difference_type value) const ENTT_NOEXCEPT {
- return {it[value].first, resource<Type>{it[value].second}};
- }
- [[nodiscard]] reference operator*() const ENTT_NOEXCEPT {
- return (*this)[0];
- }
- [[nodiscard]] pointer operator->() const ENTT_NOEXCEPT {
- return operator*();
- }
- template<typename TLhs, typename ILhs, typename TRhs, typename IRhs>
- friend std::ptrdiff_t operator-(const resource_cache_iterator<TLhs, ILhs> &, const resource_cache_iterator<TRhs, IRhs> &) ENTT_NOEXCEPT;
- template<typename TLhs, typename ILhs, typename TRhs, typename IRhs>
- friend bool operator==(const resource_cache_iterator<TLhs, ILhs> &, const resource_cache_iterator<TRhs, IRhs> &) ENTT_NOEXCEPT;
- template<typename TLhs, typename ILhs, typename TRhs, typename IRhs>
- friend bool operator<(const resource_cache_iterator<TLhs, ILhs> &, const resource_cache_iterator<TRhs, IRhs> &) ENTT_NOEXCEPT;
- private:
- It it;
- };
- template<typename TLhs, typename ILhs, typename TRhs, typename IRhs>
- [[nodiscard]] std::ptrdiff_t operator-(const resource_cache_iterator<TLhs, ILhs> &lhs, const resource_cache_iterator<TRhs, IRhs> &rhs) ENTT_NOEXCEPT {
- return lhs.it - rhs.it;
- }
- template<typename TLhs, typename ILhs, typename TRhs, typename IRhs>
- [[nodiscard]] bool operator==(const resource_cache_iterator<TLhs, ILhs> &lhs, const resource_cache_iterator<TRhs, IRhs> &rhs) ENTT_NOEXCEPT {
- return lhs.it == rhs.it;
- }
- template<typename TLhs, typename ILhs, typename TRhs, typename IRhs>
- [[nodiscard]] bool operator!=(const resource_cache_iterator<TLhs, ILhs> &lhs, const resource_cache_iterator<TRhs, IRhs> &rhs) ENTT_NOEXCEPT {
- return !(lhs == rhs);
- }
- template<typename TLhs, typename ILhs, typename TRhs, typename IRhs>
- [[nodiscard]] bool operator<(const resource_cache_iterator<TLhs, ILhs> &lhs, const resource_cache_iterator<TRhs, IRhs> &rhs) ENTT_NOEXCEPT {
- return lhs.it < rhs.it;
- }
- template<typename TLhs, typename ILhs, typename TRhs, typename IRhs>
- [[nodiscard]] bool operator>(const resource_cache_iterator<TLhs, ILhs> &lhs, const resource_cache_iterator<TRhs, IRhs> &rhs) ENTT_NOEXCEPT {
- return rhs < lhs;
- }
- template<typename TLhs, typename ILhs, typename TRhs, typename IRhs>
- [[nodiscard]] bool operator<=(const resource_cache_iterator<TLhs, ILhs> &lhs, const resource_cache_iterator<TRhs, IRhs> &rhs) ENTT_NOEXCEPT {
- return !(lhs > rhs);
- }
- template<typename TLhs, typename ILhs, typename TRhs, typename IRhs>
- [[nodiscard]] bool operator>=(const resource_cache_iterator<TLhs, ILhs> &lhs, const resource_cache_iterator<TRhs, IRhs> &rhs) ENTT_NOEXCEPT {
- return !(lhs < rhs);
- }
- } // namespace internal
- /**
- * Internal details not to be documented.
- * @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 = typename 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<id_type>, container_allocator>;
- public:
- /*! @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 Allocator type. */
- using allocator_type = Allocator;
- /*! @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 &&) = 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 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 &&) = default;
- /**
- * @brief Returns the associated allocator.
- * @return The associated allocator.
- */
- [[nodiscard]] constexpr allocator_type get_allocator() const ENTT_NOEXCEPT {
- return pool.first().get_allocator();
- }
- /**
- * @brief Returns an iterator to the beginning.
- *
- * The returned iterator points to the first instance of the cache. 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 ENTT_NOEXCEPT {
- return pool.first().begin();
- }
- /*! @copydoc cbegin */
- [[nodiscard]] const_iterator begin() const ENTT_NOEXCEPT {
- return cbegin();
- }
- /*! @copydoc begin */
- [[nodiscard]] iterator begin() ENTT_NOEXCEPT {
- return pool.first().begin();
- }
- /**
- * @brief Returns an iterator to the end.
- *
- * The returned iterator points to the element following the last instance
- * of the cache. Attempting to dereference the returned iterator results in
- * undefined behavior.
- *
- * @return An iterator to the element following the last instance of the
- * internal cache.
- */
- [[nodiscard]] const_iterator cend() const ENTT_NOEXCEPT {
- return pool.first().end();
- }
- /*! @copydoc cend */
- [[nodiscard]] const_iterator end() const ENTT_NOEXCEPT {
- return cend();
- }
- /*! @copydoc end */
- [[nodiscard]] iterator end() ENTT_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 ENTT_NOEXCEPT {
- return pool.first().empty();
- }
- /**
- * @brief Number of resources managed by a cache.
- * @return Number of resources currently stored.
- */
- [[nodiscard]] size_type size() const ENTT_NOEXCEPT {
- return pool.first().size();
- }
- /*! @brief Clears a cache. */
- void clear() ENTT_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 "../config/config.h"
- // #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 {
- /*! @brief Resource handles are friends with each other. */
- template<typename>
- friend class resource;
- template<typename Other>
- static constexpr bool is_acceptable_v = !std::is_same_v<Type, Other> && std::is_constructible_v<Type &, Other &>;
- public:
- /*! @brief Default constructor. */
- resource() ENTT_NOEXCEPT
- : value{} {}
- /**
- * @brief Creates a handle from a weak pointer, namely a resource.
- * @param res A weak pointer to a resource.
- */
- explicit resource(std::shared_ptr<Type> res) ENTT_NOEXCEPT
- : value{std::move(res)} {}
- /*! @brief Default copy constructor. */
- resource(const resource &) ENTT_NOEXCEPT = default;
- /*! @brief Default move constructor. */
- resource(resource &&) ENTT_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, Type &res) ENTT_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_v<Other>>>
- resource(const resource<Other> &other) ENTT_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_v<Other>>>
- resource(resource<Other> &&other) ENTT_NOEXCEPT
- : value{std::move(other.value)} {}
- /**
- * @brief Default copy assignment operator.
- * @return This resource handle.
- */
- resource &operator=(const resource &) ENTT_NOEXCEPT = default;
- /**
- * @brief Default move assignment operator.
- * @return This resource handle.
- */
- resource &operator=(resource &&) ENTT_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>
- std::enable_if_t<is_acceptable_v<Other>, resource &>
- operator=(const resource<Other> &other) ENTT_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>
- std::enable_if_t<is_acceptable_v<Other>, resource &>
- operator=(resource<Other> &&other) ENTT_NOEXCEPT {
- value = std::move(other.value);
- return *this;
- }
- /**
- * @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]] Type &operator*() const ENTT_NOEXCEPT {
- return *value;
- }
- /*! @copydoc operator* */
- [[nodiscard]] operator Type &() const ENTT_NOEXCEPT {
- return *value;
- }
- /**
- * @brief Returns a pointer to the managed resource.
- * @return A pointer to the managed resource.
- */
- [[nodiscard]] Type *operator->() const ENTT_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 ENTT_NOEXCEPT {
- return static_cast<bool>(value);
- }
- /**
- * @brief Returns the number of handles pointing the same resource.
- * @return The number of handles pointing the same resource.
- */
- [[nodiscard]] long use_count() const ENTT_NOEXCEPT {
- return value.use_count();
- }
- private:
- std::shared_ptr<Type> value;
- };
- /**
- * @brief Compares two handles.
- * @tparam Res Type of resource managed by the first handle.
- * @tparam Other 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 Res, typename Other>
- [[nodiscard]] bool operator==(const resource<Res> &lhs, const resource<Other> &rhs) ENTT_NOEXCEPT {
- return (std::addressof(*lhs) == std::addressof(*rhs));
- }
- /**
- * @brief Compares two handles.
- * @tparam Res Type of resource managed by the first handle.
- * @tparam Other 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 registry, true otherwise.
- */
- template<typename Res, typename Other>
- [[nodiscard]] bool operator!=(const resource<Res> &lhs, const resource<Other> &rhs) ENTT_NOEXCEPT {
- return !(lhs == rhs);
- }
- /**
- * @brief Compares two handles.
- * @tparam Res Type of resource managed by the first handle.
- * @tparam Other 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 Res, typename Other>
- [[nodiscard]] bool operator<(const resource<Res> &lhs, const resource<Other> &rhs) ENTT_NOEXCEPT {
- return (std::addressof(*lhs) < std::addressof(*rhs));
- }
- /**
- * @brief Compares two handles.
- * @tparam Res Type of resource managed by the first handle.
- * @tparam Other 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 Res, typename Other>
- [[nodiscard]] bool operator>(const resource<Res> &lhs, const resource<Other> &rhs) ENTT_NOEXCEPT {
- return (std::addressof(*lhs) > std::addressof(*rhs));
- }
- /**
- * @brief Compares two handles.
- * @tparam Res Type of resource managed by the first handle.
- * @tparam Other 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 Res, typename Other>
- [[nodiscard]] bool operator<=(const resource<Res> &lhs, const resource<Other> &rhs) ENTT_NOEXCEPT {
- return !(lhs > rhs);
- }
- /**
- * @brief Compares two handles.
- * @tparam Res Type of resource managed by the first handle.
- * @tparam Other 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 Res, typename Other>
- [[nodiscard]] bool operator>=(const resource<Res> &lhs, const resource<Other> &rhs) ENTT_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
- #define ENTT_STR(arg) #arg
- #define ENTT_XSTR(arg) ENTT_STR(arg)
- #endif
- #define ENTT_VERSION_MAJOR 3
- #define ENTT_VERSION_MINOR 10
- #define ENTT_VERSION_PATCH 3
- #define ENTT_VERSION \
- ENTT_XSTR(ENTT_VERSION_MAJOR) \
- "." ENTT_XSTR(ENTT_VERSION_MINOR) "." ENTT_XSTR(ENTT_VERSION_PATCH)
- #endif
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #ifndef ENTT_NOEXCEPT
- # define ENTT_NOEXCEPT noexcept
- # define ENTT_NOEXCEPT_IF(expr) noexcept(expr)
- # else
- # define ENTT_NOEXCEPT_IF(...)
- #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
- #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(...) (void(0))
- #elif !defined ENTT_ASSERT
- # include <cassert>
- # define ENTT_ASSERT(condition, ...) assert(condition)
- #endif
- #ifdef ENTT_NO_ETO
- # define ENTT_IGNORE_IF_EMPTY false
- #else
- # define ENTT_IGNORE_IF_EMPTY true
- #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
- #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
- #endif
- // #include "../core/type_traits.hpp"
- #ifndef ENTT_CORE_TYPE_TRAITS_HPP
- #define ENTT_CORE_TYPE_TRAITS_HPP
- #include <cstddef>
- #include <iterator>
- #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
- #define ENTT_STR(arg) #arg
- #define ENTT_XSTR(arg) ENTT_STR(arg)
- #endif
- #define ENTT_VERSION_MAJOR 3
- #define ENTT_VERSION_MINOR 10
- #define ENTT_VERSION_PATCH 3
- #define ENTT_VERSION \
- ENTT_XSTR(ENTT_VERSION_MAJOR) \
- "." ENTT_XSTR(ENTT_VERSION_MINOR) "." ENTT_XSTR(ENTT_VERSION_PATCH)
- #endif
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #ifndef ENTT_NOEXCEPT
- # define ENTT_NOEXCEPT noexcept
- # define ENTT_NOEXCEPT_IF(expr) noexcept(expr)
- # else
- # define ENTT_NOEXCEPT_IF(...)
- #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
- #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(...) (void(0))
- #elif !defined ENTT_ASSERT
- # include <cassert>
- # define ENTT_ASSERT(condition, ...) assert(condition)
- #endif
- #ifdef ENTT_NO_ETO
- # define ENTT_IGNORE_IF_EMPTY false
- #else
- # define ENTT_IGNORE_IF_EMPTY true
- #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
- #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
- #endif
- // #include "fwd.hpp"
- #ifndef ENTT_CORE_FWD_HPP
- #define ENTT_CORE_FWD_HPP
- #include <cstdint>
- #include <type_traits>
- // #include "../config/config.h"
- namespace entt {
- template<std::size_t Len = sizeof(double[2]), std::size_t = alignof(typename std::aligned_storage_t<Len + !Len>)>
- 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<>;
- } // 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.
- * @tparam The size of the type if `sizeof` accepts it, 0 otherwise.
- */
- 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))>>
- : 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 Type First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<std::size_t Index, typename Type, typename... Other>
- struct type_list_element<Index, type_list<Type, Other...>>
- : type_list_element<Index - 1u, type_list<Other...>> {};
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam Type First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<typename Type, typename... Other>
- struct type_list_element<0u, type_list<Type, Other...>> {
- /*! @brief Searched type. */
- using type = Type;
- };
- /**
- * @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 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;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename>
- struct type_list_unique;
- /**
- * @brief Removes duplicates types from a type list.
- * @tparam Type One of the types provided by the given type list.
- * @tparam Other The other types provided by the given type list.
- */
- template<typename Type, typename... Other>
- struct type_list_unique<type_list<Type, Other...>> {
- /*! @brief A type list without duplicate types. */
- using type = std::conditional_t<
- (std::is_same_v<Type, Other> || ...),
- typename type_list_unique<type_list<Other...>>::type,
- type_list_cat_t<type_list<Type>, typename type_list_unique<type_list<Other...>>::type>>;
- };
- /*! @brief Removes duplicates types from a type list. */
- template<>
- struct type_list_unique<type_list<>> {
- /*! @brief A type list without duplicate types. */
- using type = type_list<>;
- };
- /**
- * @brief Helper type.
- * @tparam Type A type list.
- */
- template<typename Type>
- using type_list_unique_t = typename type_list_unique<Type>::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::disjunction<std::is_same<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 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 value. */
- static constexpr auto value = Value;
- };
- /**
- * @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 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 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
- * Internal details not to be documented.
- */
- 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
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /*! @copydoc is_iterator */
- template<typename Type>
- struct is_iterator<Type, std::enable_if_t<!std::is_same_v<std::remove_const_t<std::remove_pointer_t<Type>>, void>>>
- : 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::conjunction<std::is_empty<Type>, std::negation<std::is_final<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;
- /**
- * @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, typename = void>
- struct is_equality_comparable: std::false_type {};
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- 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 Type, std::size_t... Index>
- [[nodiscard]] constexpr bool unpack_maybe_equality_comparable(std::index_sequence<Index...>) {
- return (is_equality_comparable<std::tuple_element_t<Index, Type>>::value && ...);
- }
- template<typename>
- [[nodiscard]] constexpr bool maybe_equality_comparable(choice_t<0>) {
- return true;
- }
- template<typename Type>
- [[nodiscard]] constexpr auto maybe_equality_comparable(choice_t<1>) -> decltype(std::declval<typename Type::value_type>(), bool{}) {
- if constexpr(is_iterator_v<Type>) {
- return true;
- } else if constexpr(std::is_same_v<typename Type::value_type, Type>) {
- return maybe_equality_comparable<Type>(choice<0>);
- } else {
- return is_equality_comparable<typename Type::value_type>::value;
- }
- }
- template<typename Type>
- [[nodiscard]] constexpr std::enable_if_t<is_complete_v<std::tuple_size<std::remove_const_t<Type>>>, bool> maybe_equality_comparable(choice_t<2>) {
- if constexpr(has_tuple_size_value<Type>::value) {
- return unpack_maybe_equality_comparable<Type>(std::make_index_sequence<std::tuple_size<Type>::value>{});
- } else {
- return maybe_equality_comparable<Type>(choice<1>);
- }
- }
- } // namespace internal
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /*! @copydoc is_equality_comparable */
- template<typename Type>
- struct is_equality_comparable<Type, std::void_t<decltype(std::declval<Type>() == std::declval<Type>())>>
- : std::bool_constant<internal::maybe_equality_comparable<Type>(choice<2>)> {};
- /**
- * @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 = std::add_const_t<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;
- } // namespace entt
- #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<char>>
- class basic_dispatcher;
- template<typename>
- class emitter;
- class connection;
- struct scoped_connection;
- template<typename>
- class sink;
- template<typename Type, typename = std::allocator<Type *>>
- class sigh;
- /*! @brief Alias declaration for the most common use case. */
- using dispatcher = basic_dispatcher<>;
- } // namespace entt
- #endif
- namespace entt {
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- namespace internal {
- template<typename Ret, typename... Args>
- auto function_pointer(Ret (*)(Args...)) -> Ret (*)(Args...);
- template<typename Ret, typename Type, typename... Args, typename Other>
- auto function_pointer(Ret (*)(Type, Args...), Other &&) -> Ret (*)(Args...);
- template<typename Class, typename Ret, typename... Args, typename... Other>
- auto function_pointer(Ret (Class::*)(Args...), Other &&...) -> Ret (*)(Args...);
- template<typename Class, typename Ret, typename... Args, typename... Other>
- auto function_pointer(Ret (Class::*)(Args...) const, Other &&...) -> Ret (*)(Args...);
- template<typename Class, typename Type, typename... Other>
- auto function_pointer(Type Class::*, Other &&...) -> Type (*)();
- template<typename... Type>
- using function_pointer_t = decltype(internal::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
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /*! @brief Used to wrap a function or a member of a specified type. */
- template<auto>
- struct connect_arg_t {};
- /*! @brief Constant of type connect_arg_t used to disambiguate calls. */
- template<auto Func>
- inline constexpr connect_arg_t<Func> connect_arg{};
- /**
- * @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...)> {
- template<auto Candidate, std::size_t... Index>
- [[nodiscard]] auto wrap(std::index_sequence<Index...>) ENTT_NOEXCEPT {
- return [](const void *, Args... args) -> Ret {
- [[maybe_unused]] const auto arguments = std::forward_as_tuple(std::forward<Args>(args)...);
- return static_cast<Ret>(std::invoke(Candidate, std::forward<type_list_element_t<Index, type_list<Args...>>>(std::get<Index>(arguments))...));
- };
- }
- template<auto Candidate, typename Type, std::size_t... Index>
- [[nodiscard]] auto wrap(Type &, std::index_sequence<Index...>) ENTT_NOEXCEPT {
- return [](const void *payload, Args... args) -> Ret {
- [[maybe_unused]] const auto arguments = std::forward_as_tuple(std::forward<Args>(args)...);
- Type *curr = static_cast<Type *>(const_cast<constness_as_t<void, Type> *>(payload));
- return static_cast<Ret>(std::invoke(Candidate, *curr, std::forward<type_list_element_t<Index, type_list<Args...>>>(std::get<Index>(arguments))...));
- };
- }
- template<auto Candidate, typename Type, std::size_t... Index>
- [[nodiscard]] auto wrap(Type *, std::index_sequence<Index...>) ENTT_NOEXCEPT {
- return [](const void *payload, Args... args) -> Ret {
- [[maybe_unused]] const auto arguments = std::forward_as_tuple(std::forward<Args>(args)...);
- Type *curr = static_cast<Type *>(const_cast<constness_as_t<void, Type> *>(payload));
- return static_cast<Ret>(std::invoke(Candidate, curr, std::forward<type_list_element_t<Index, type_list<Args...>>>(std::get<Index>(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() ENTT_NOEXCEPT
- : instance{nullptr},
- fn{nullptr} {}
- /**
- * @brief Constructs a delegate and connects a free function or an unbound
- * member.
- * @tparam Candidate Function or member to connect to the delegate.
- */
- template<auto Candidate>
- delegate(connect_arg_t<Candidate>) ENTT_NOEXCEPT {
- connect<Candidate>();
- }
- /**
- * @brief Constructs a delegate and connects a free function with payload or
- * a bound member.
- * @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 object that fits the purpose.
- */
- template<auto Candidate, typename Type>
- delegate(connect_arg_t<Candidate>, Type &&value_or_instance) ENTT_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) ENTT_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() ENTT_NOEXCEPT {
- instance = nullptr;
- if constexpr(std::is_invocable_r_v<Ret, decltype(Candidate), Args...>) {
- fn = [](const void *, Args... args) -> Ret {
- 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) ENTT_NOEXCEPT {
- instance = &value_or_instance;
- if constexpr(std::is_invocable_r_v<Ret, decltype(Candidate), Type &, Args...>) {
- fn = [](const void *payload, Args... args) -> Ret {
- 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) ENTT_NOEXCEPT {
- instance = value_or_instance;
- if constexpr(std::is_invocable_r_v<Ret, decltype(Candidate), Type *, Args...>) {
- fn = [](const void *payload, Args... args) -> Ret {
- 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) ENTT_NOEXCEPT {
- instance = payload;
- fn = function;
- }
- /**
- * @brief Resets a delegate.
- *
- * After a reset, a delegate cannot be invoked anymore.
- */
- void reset() ENTT_NOEXCEPT {
- instance = nullptr;
- fn = nullptr;
- }
- /**
- * @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 ENTT_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 ENTT_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 ENTT_NOEXCEPT {
- return fn == other.fn && instance == other.instance;
- }
- private:
- const void *instance;
- function_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) ENTT_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 <algorithm>
- #include <cstddef>
- #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 <algorithm>
- #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
- #define ENTT_STR(arg) #arg
- #define ENTT_XSTR(arg) ENTT_STR(arg)
- #endif
- #define ENTT_VERSION_MAJOR 3
- #define ENTT_VERSION_MINOR 10
- #define ENTT_VERSION_PATCH 3
- #define ENTT_VERSION \
- ENTT_XSTR(ENTT_VERSION_MAJOR) \
- "." ENTT_XSTR(ENTT_VERSION_MINOR) "." ENTT_XSTR(ENTT_VERSION_PATCH)
- #endif
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #ifndef ENTT_NOEXCEPT
- # define ENTT_NOEXCEPT noexcept
- # define ENTT_NOEXCEPT_IF(expr) noexcept(expr)
- # else
- # define ENTT_NOEXCEPT_IF(...)
- #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
- #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(...) (void(0))
- #elif !defined ENTT_ASSERT
- # include <cassert>
- # define ENTT_ASSERT(condition, ...) assert(condition)
- #endif
- #ifdef ENTT_NO_ETO
- # define ENTT_IGNORE_IF_EMPTY false
- #else
- # define ENTT_IGNORE_IF_EMPTY true
- #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
- #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
- #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 "../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
- #define ENTT_STR(arg) #arg
- #define ENTT_XSTR(arg) ENTT_STR(arg)
- #endif
- #define ENTT_VERSION_MAJOR 3
- #define ENTT_VERSION_MINOR 10
- #define ENTT_VERSION_PATCH 3
- #define ENTT_VERSION \
- ENTT_XSTR(ENTT_VERSION_MAJOR) \
- "." ENTT_XSTR(ENTT_VERSION_MINOR) "." ENTT_XSTR(ENTT_VERSION_PATCH)
- #endif
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #ifndef ENTT_NOEXCEPT
- # define ENTT_NOEXCEPT noexcept
- # define ENTT_NOEXCEPT_IF(expr) noexcept(expr)
- # else
- # define ENTT_NOEXCEPT_IF(...)
- #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
- #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(...) (void(0))
- #elif !defined ENTT_ASSERT
- # include <cassert>
- # define ENTT_ASSERT(condition, ...) assert(condition)
- #endif
- #ifdef ENTT_NO_ETO
- # define ENTT_IGNORE_IF_EMPTY false
- #else
- # define ENTT_IGNORE_IF_EMPTY true
- #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
- #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
- #endif
- // #include "type_traits.hpp"
- #ifndef ENTT_CORE_TYPE_TRAITS_HPP
- #define ENTT_CORE_TYPE_TRAITS_HPP
- #include <cstddef>
- #include <iterator>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- // #include "fwd.hpp"
- #ifndef ENTT_CORE_FWD_HPP
- #define ENTT_CORE_FWD_HPP
- #include <cstdint>
- #include <type_traits>
- // #include "../config/config.h"
- namespace entt {
- template<std::size_t Len = sizeof(double[2]), std::size_t = alignof(typename std::aligned_storage_t<Len + !Len>)>
- 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<>;
- } // 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.
- * @tparam The size of the type if `sizeof` accepts it, 0 otherwise.
- */
- 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))>>
- : 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 Type First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<std::size_t Index, typename Type, typename... Other>
- struct type_list_element<Index, type_list<Type, Other...>>
- : type_list_element<Index - 1u, type_list<Other...>> {};
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam Type First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<typename Type, typename... Other>
- struct type_list_element<0u, type_list<Type, Other...>> {
- /*! @brief Searched type. */
- using type = Type;
- };
- /**
- * @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 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;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename>
- struct type_list_unique;
- /**
- * @brief Removes duplicates types from a type list.
- * @tparam Type One of the types provided by the given type list.
- * @tparam Other The other types provided by the given type list.
- */
- template<typename Type, typename... Other>
- struct type_list_unique<type_list<Type, Other...>> {
- /*! @brief A type list without duplicate types. */
- using type = std::conditional_t<
- (std::is_same_v<Type, Other> || ...),
- typename type_list_unique<type_list<Other...>>::type,
- type_list_cat_t<type_list<Type>, typename type_list_unique<type_list<Other...>>::type>>;
- };
- /*! @brief Removes duplicates types from a type list. */
- template<>
- struct type_list_unique<type_list<>> {
- /*! @brief A type list without duplicate types. */
- using type = type_list<>;
- };
- /**
- * @brief Helper type.
- * @tparam Type A type list.
- */
- template<typename Type>
- using type_list_unique_t = typename type_list_unique<Type>::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::disjunction<std::is_same<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 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 value. */
- static constexpr auto value = Value;
- };
- /**
- * @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 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 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
- * Internal details not to be documented.
- */
- 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
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /*! @copydoc is_iterator */
- template<typename Type>
- struct is_iterator<Type, std::enable_if_t<!std::is_same_v<std::remove_const_t<std::remove_pointer_t<Type>>, void>>>
- : 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::conjunction<std::is_empty<Type>, std::negation<std::is_final<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;
- /**
- * @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, typename = void>
- struct is_equality_comparable: std::false_type {};
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- 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 Type, std::size_t... Index>
- [[nodiscard]] constexpr bool unpack_maybe_equality_comparable(std::index_sequence<Index...>) {
- return (is_equality_comparable<std::tuple_element_t<Index, Type>>::value && ...);
- }
- template<typename>
- [[nodiscard]] constexpr bool maybe_equality_comparable(choice_t<0>) {
- return true;
- }
- template<typename Type>
- [[nodiscard]] constexpr auto maybe_equality_comparable(choice_t<1>) -> decltype(std::declval<typename Type::value_type>(), bool{}) {
- if constexpr(is_iterator_v<Type>) {
- return true;
- } else if constexpr(std::is_same_v<typename Type::value_type, Type>) {
- return maybe_equality_comparable<Type>(choice<0>);
- } else {
- return is_equality_comparable<typename Type::value_type>::value;
- }
- }
- template<typename Type>
- [[nodiscard]] constexpr std::enable_if_t<is_complete_v<std::tuple_size<std::remove_const_t<Type>>>, bool> maybe_equality_comparable(choice_t<2>) {
- if constexpr(has_tuple_size_value<Type>::value) {
- return unpack_maybe_equality_comparable<Type>(std::make_index_sequence<std::tuple_size<Type>::value>{});
- } else {
- return maybe_equality_comparable<Type>(choice<1>);
- }
- }
- } // namespace internal
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /*! @copydoc is_equality_comparable */
- template<typename Type>
- struct is_equality_comparable<Type, std::void_t<decltype(std::declval<Type>() == std::declval<Type>())>>
- : std::bool_constant<internal::maybe_equality_comparable<Type>(choice<2>)> {};
- /**
- * @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 = std::add_const_t<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;
- } // namespace entt
- #endif
- namespace entt {
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- namespace internal {
- template<typename Type, std::size_t, typename = void>
- struct compressed_pair_element {
- using reference = Type &;
- using const_reference = const Type &;
- template<bool Dummy = true, typename = std::enable_if_t<Dummy && std::is_default_constructible_v<Type>>>
- compressed_pair_element()
- : value{} {}
- template<typename Args, typename = std::enable_if_t<!std::is_same_v<std::remove_cv_t<std::remove_reference_t<Args>>, compressed_pair_element>>>
- compressed_pair_element(Args &&args)
- : value{std::forward<Args>(args)} {}
- template<typename... Args, std::size_t... Index>
- compressed_pair_element(std::tuple<Args...> args, std::index_sequence<Index...>)
- : value{std::forward<Args>(std::get<Index>(args))...} {}
- [[nodiscard]] reference get() ENTT_NOEXCEPT {
- return value;
- }
- [[nodiscard]] const_reference get() const ENTT_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<bool Dummy = true, typename = std::enable_if_t<Dummy && std::is_default_constructible_v<base_type>>>
- compressed_pair_element()
- : base_type{} {}
- template<typename Args, typename = std::enable_if_t<!std::is_same_v<std::remove_cv_t<std::remove_reference_t<Args>>, compressed_pair_element>>>
- compressed_pair_element(Args &&args)
- : base_type{std::forward<Args>(args)} {}
- template<typename... Args, std::size_t... Index>
- compressed_pair_element(std::tuple<Args...> args, std::index_sequence<Index...>)
- : base_type{std::forward<Args>(std::get<Index>(args))...} {}
- [[nodiscard]] reference get() ENTT_NOEXCEPT {
- return *this;
- }
- [[nodiscard]] const_reference get() const ENTT_NOEXCEPT {
- return *this;
- }
- };
- } // namespace internal
- /**
- * Internal details not to be documented.
- * @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()
- : 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) = 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)
- : 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)
- : first_base{std::move(args), std::index_sequence_for<Args...>{}},
- second_base{std::move(other), std::index_sequence_for<Other...>{}} {}
- /**
- * @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) = default;
- /**
- * @brief Returns the first element that a pair stores.
- * @return The first element that a pair stores.
- */
- [[nodiscard]] first_type &first() ENTT_NOEXCEPT {
- return static_cast<first_base &>(*this).get();
- }
- /*! @copydoc first */
- [[nodiscard]] const first_type &first() const ENTT_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]] second_type &second() ENTT_NOEXCEPT {
- return static_cast<second_base &>(*this).get();
- }
- /*! @copydoc second */
- [[nodiscard]] const second_type &second() const ENTT_NOEXCEPT {
- return static_cast<const second_base &>(*this).get();
- }
- /**
- * @brief Swaps two compressed pair objects.
- * @param other The compressed pair to swap with.
- */
- void swap(compressed_pair &other) {
- 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>
- decltype(auto) get() ENTT_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>
- decltype(auto) get() const ENTT_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>
- inline void swap(compressed_pair<First, Second> &lhs, compressed_pair<First, Second> &rhs) {
- lhs.swap(rhs);
- }
- } // namespace entt
- // disable structured binding support for clang 6, it messes when specializing tuple_size
- #if !defined __clang_major__ || __clang_major__ > 6
- 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
- #endif
- // #include "../core/iterator.hpp"
- #ifndef ENTT_CORE_ITERATOR_HPP
- #define ENTT_CORE_ITERATOR_HPP
- #include <iterator>
- #include <memory>
- #include <utility>
- // #include "../config/config.h"
- 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 Pointer type. */
- using pointer = Type *;
- /*! @brief Default copy constructor, deleted on purpose. */
- input_iterator_pointer(const input_iterator_pointer &) = delete;
- /*! @brief Default move constructor. */
- input_iterator_pointer(input_iterator_pointer &&) = default;
- /**
- * @brief Constructs a proxy object by move.
- * @param val Value to use to initialize the proxy object.
- */
- input_iterator_pointer(Type &&val)
- : value{std::move(val)} {}
- /**
- * @brief Default copy assignment operator, deleted on purpose.
- * @return This proxy object.
- */
- input_iterator_pointer &operator=(const input_iterator_pointer &) = delete;
- /**
- * @brief Default move assignment operator.
- * @return This proxy object.
- */
- input_iterator_pointer &operator=(input_iterator_pointer &&) = default;
- /**
- * @brief Access operator for accessing wrapped values.
- * @return A pointer to the wrapped value.
- */
- [[nodiscard]] pointer operator->() ENTT_NOEXCEPT {
- return std::addressof(value);
- }
- private:
- Type value;
- };
- /**
- * @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. */
- iterable_adaptor() = default;
- /**
- * @brief Creates an iterable object from a pair of iterators.
- * @param from Begin iterator.
- * @param to End iterator.
- */
- iterable_adaptor(iterator from, sentinel to)
- : first{from},
- last{to} {}
- /**
- * @brief Returns an iterator to the beginning.
- * @return An iterator to the first element of the range.
- */
- [[nodiscard]] iterator begin() const ENTT_NOEXCEPT {
- return first;
- }
- /**
- * @brief Returns an iterator to the end.
- * @return An iterator to the element following the last element of the
- * range.
- */
- [[nodiscard]] sentinel end() const ENTT_NOEXCEPT {
- return last;
- }
- /*! @copydoc begin */
- [[nodiscard]] iterator cbegin() const ENTT_NOEXCEPT {
- return begin();
- }
- /*! @copydoc end */
- [[nodiscard]] sentinel cend() const ENTT_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 <limits>
- #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) ENTT_NOEXCEPT {
- if constexpr(std::is_pointer_v<std::remove_cv_t<std::remove_reference_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) ENTT_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) ENTT_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) ENTT_NOEXCEPT {
- ENTT_ASSERT(std::allocator_traits<Allocator>::propagate_on_container_swap::value || lhs == rhs, "Cannot swap the containers");
- if constexpr(std::allocator_traits<Allocator>::propagate_on_container_swap::value) {
- using std::swap;
- swap(lhs, rhs);
- }
- }
- /**
- * @brief Checks whether a value is a power of two or not.
- * @param value A value that may or may not be a power of two.
- * @return True if the value is a power of two, false otherwise.
- */
- [[nodiscard]] inline constexpr bool is_power_of_two(const std::size_t value) ENTT_NOEXCEPT {
- return value && ((value & (value - 1)) == 0);
- }
- /**
- * @brief Computes the smallest power of two greater than or equal to a value.
- * @param value The value to use.
- * @return The smallest power of two greater than or equal to the given value.
- */
- [[nodiscard]] inline constexpr std::size_t next_power_of_two(const std::size_t value) ENTT_NOEXCEPT {
- ENTT_ASSERT(value < (std::size_t{1u} << (std::numeric_limits<std::size_t>::digits - 1)), "Numeric limits exceeded");
- std::size_t curr = value - (value != 0u);
- for(int next = 1; next < std::numeric_limits<std::size_t>::digits; next = next * 2) {
- curr |= curr >> next;
- }
- return ++curr;
- }
- /**
- * @brief Fast module utility function (powers of two only).
- * @param value A value for which to calculate the modulus.
- * @param mod _Modulus_, it must be a power of two.
- * @return The common remainder.
- */
- [[nodiscard]] inline constexpr std::size_t fast_mod(const std::size_t value, const std::size_t mod) ENTT_NOEXCEPT {
- ENTT_ASSERT(is_power_of_two(mod), "Value must be a power of two");
- return value & (mod - 1u);
- }
- /**
- * @brief Deleter for allocator-aware unique pointers (waiting for C++20).
- * @tparam Args Types of arguments to use to construct the object.
- */
- 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.
- */
- allocation_deleter(const allocator_type &alloc)
- : Allocator{alloc} {}
- /**
- * @brief Destroys the pointed object and deallocates its memory.
- * @param ptr A valid pointer to an object of the given type.
- */
- void operator()(pointer ptr) {
- using alloc_traits = typename 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>
- 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
- * Internal details not to be documented.
- */
- 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) ENTT_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) ENTT_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) ENTT_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) ENTT_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) ENTT_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) ENTT_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
- /**
- * Internal details not to be documented.
- * @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) ENTT_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([&](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 <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.
- * @tparam The size of the type if `sizeof` accepts it, 0 otherwise.
- */
- 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))>>
- : 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 Type First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<std::size_t Index, typename Type, typename... Other>
- struct type_list_element<Index, type_list<Type, Other...>>
- : type_list_element<Index - 1u, type_list<Other...>> {};
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam Type First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<typename Type, typename... Other>
- struct type_list_element<0u, type_list<Type, Other...>> {
- /*! @brief Searched type. */
- using type = Type;
- };
- /**
- * @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 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;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename>
- struct type_list_unique;
- /**
- * @brief Removes duplicates types from a type list.
- * @tparam Type One of the types provided by the given type list.
- * @tparam Other The other types provided by the given type list.
- */
- template<typename Type, typename... Other>
- struct type_list_unique<type_list<Type, Other...>> {
- /*! @brief A type list without duplicate types. */
- using type = std::conditional_t<
- (std::is_same_v<Type, Other> || ...),
- typename type_list_unique<type_list<Other...>>::type,
- type_list_cat_t<type_list<Type>, typename type_list_unique<type_list<Other...>>::type>>;
- };
- /*! @brief Removes duplicates types from a type list. */
- template<>
- struct type_list_unique<type_list<>> {
- /*! @brief A type list without duplicate types. */
- using type = type_list<>;
- };
- /**
- * @brief Helper type.
- * @tparam Type A type list.
- */
- template<typename Type>
- using type_list_unique_t = typename type_list_unique<Type>::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::disjunction<std::is_same<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 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 value. */
- static constexpr auto value = Value;
- };
- /**
- * @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 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 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
- * Internal details not to be documented.
- */
- 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
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /*! @copydoc is_iterator */
- template<typename Type>
- struct is_iterator<Type, std::enable_if_t<!std::is_same_v<std::remove_const_t<std::remove_pointer_t<Type>>, void>>>
- : 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::conjunction<std::is_empty<Type>, std::negation<std::is_final<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;
- /**
- * @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, typename = void>
- struct is_equality_comparable: std::false_type {};
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- 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 Type, std::size_t... Index>
- [[nodiscard]] constexpr bool unpack_maybe_equality_comparable(std::index_sequence<Index...>) {
- return (is_equality_comparable<std::tuple_element_t<Index, Type>>::value && ...);
- }
- template<typename>
- [[nodiscard]] constexpr bool maybe_equality_comparable(choice_t<0>) {
- return true;
- }
- template<typename Type>
- [[nodiscard]] constexpr auto maybe_equality_comparable(choice_t<1>) -> decltype(std::declval<typename Type::value_type>(), bool{}) {
- if constexpr(is_iterator_v<Type>) {
- return true;
- } else if constexpr(std::is_same_v<typename Type::value_type, Type>) {
- return maybe_equality_comparable<Type>(choice<0>);
- } else {
- return is_equality_comparable<typename Type::value_type>::value;
- }
- }
- template<typename Type>
- [[nodiscard]] constexpr std::enable_if_t<is_complete_v<std::tuple_size<std::remove_const_t<Type>>>, bool> maybe_equality_comparable(choice_t<2>) {
- if constexpr(has_tuple_size_value<Type>::value) {
- return unpack_maybe_equality_comparable<Type>(std::make_index_sequence<std::tuple_size<Type>::value>{});
- } else {
- return maybe_equality_comparable<Type>(choice<1>);
- }
- }
- } // namespace internal
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /*! @copydoc is_equality_comparable */
- template<typename Type>
- struct is_equality_comparable<Type, std::void_t<decltype(std::declval<Type>() == std::declval<Type>())>>
- : std::bool_constant<internal::maybe_equality_comparable<Type>(choice<2>)> {};
- /**
- * @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 = std::add_const_t<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;
- } // namespace entt
- #endif
- // #include "fwd.hpp"
- #ifndef ENTT_CONTAINER_FWD_HPP
- #define ENTT_CONTAINER_FWD_HPP
- #include <functional>
- #include <memory>
- namespace entt {
- template<
- typename Key,
- typename Type,
- typename = std::hash<Key>,
- typename = std::equal_to<Key>,
- typename = std::allocator<std::pair<const Key, Type>>>
- class dense_map;
- template<
- typename Type,
- typename = std::hash<Type>,
- typename = std::equal_to<Type>,
- typename = std::allocator<Type>>
- class dense_set;
- } // namespace entt
- #endif
- namespace entt {
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- namespace internal {
- 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;
- dense_map_iterator() ENTT_NOEXCEPT
- : it{} {}
- dense_map_iterator(const It iter) ENTT_NOEXCEPT
- : it{iter} {}
- template<typename Other, typename = std::enable_if_t<!std::is_same_v<It, Other> && std::is_constructible_v<It, Other>>>
- dense_map_iterator(const dense_map_iterator<Other> &other) ENTT_NOEXCEPT
- : it{other.it} {}
- dense_map_iterator &operator++() ENTT_NOEXCEPT {
- return ++it, *this;
- }
- dense_map_iterator operator++(int) ENTT_NOEXCEPT {
- dense_map_iterator orig = *this;
- return ++(*this), orig;
- }
- dense_map_iterator &operator--() ENTT_NOEXCEPT {
- return --it, *this;
- }
- dense_map_iterator operator--(int) ENTT_NOEXCEPT {
- dense_map_iterator orig = *this;
- return operator--(), orig;
- }
- dense_map_iterator &operator+=(const difference_type value) ENTT_NOEXCEPT {
- it += value;
- return *this;
- }
- dense_map_iterator operator+(const difference_type value) const ENTT_NOEXCEPT {
- dense_map_iterator copy = *this;
- return (copy += value);
- }
- dense_map_iterator &operator-=(const difference_type value) ENTT_NOEXCEPT {
- return (*this += -value);
- }
- dense_map_iterator operator-(const difference_type value) const ENTT_NOEXCEPT {
- return (*this + -value);
- }
- [[nodiscard]] reference operator[](const difference_type value) const ENTT_NOEXCEPT {
- return {it[value].element.first, it[value].element.second};
- }
- [[nodiscard]] pointer operator->() const ENTT_NOEXCEPT {
- return operator*();
- }
- [[nodiscard]] reference operator*() const ENTT_NOEXCEPT {
- return {it->element.first, it->element.second};
- }
- template<typename ILhs, typename IRhs>
- friend std::ptrdiff_t operator-(const dense_map_iterator<ILhs> &, const dense_map_iterator<IRhs> &) ENTT_NOEXCEPT;
- template<typename ILhs, typename IRhs>
- friend bool operator==(const dense_map_iterator<ILhs> &, const dense_map_iterator<IRhs> &) ENTT_NOEXCEPT;
- template<typename ILhs, typename IRhs>
- friend bool operator<(const dense_map_iterator<ILhs> &, const dense_map_iterator<IRhs> &) ENTT_NOEXCEPT;
- private:
- It it;
- };
- template<typename ILhs, typename IRhs>
- [[nodiscard]] std::ptrdiff_t operator-(const dense_map_iterator<ILhs> &lhs, const dense_map_iterator<IRhs> &rhs) ENTT_NOEXCEPT {
- return lhs.it - rhs.it;
- }
- template<typename ILhs, typename IRhs>
- [[nodiscard]] bool operator==(const dense_map_iterator<ILhs> &lhs, const dense_map_iterator<IRhs> &rhs) ENTT_NOEXCEPT {
- return lhs.it == rhs.it;
- }
- template<typename ILhs, typename IRhs>
- [[nodiscard]] bool operator!=(const dense_map_iterator<ILhs> &lhs, const dense_map_iterator<IRhs> &rhs) ENTT_NOEXCEPT {
- return !(lhs == rhs);
- }
- template<typename ILhs, typename IRhs>
- [[nodiscard]] bool operator<(const dense_map_iterator<ILhs> &lhs, const dense_map_iterator<IRhs> &rhs) ENTT_NOEXCEPT {
- return lhs.it < rhs.it;
- }
- template<typename ILhs, typename IRhs>
- [[nodiscard]] bool operator>(const dense_map_iterator<ILhs> &lhs, const dense_map_iterator<IRhs> &rhs) ENTT_NOEXCEPT {
- return rhs < lhs;
- }
- template<typename ILhs, typename IRhs>
- [[nodiscard]] bool operator<=(const dense_map_iterator<ILhs> &lhs, const dense_map_iterator<IRhs> &rhs) ENTT_NOEXCEPT {
- return !(lhs > rhs);
- }
- template<typename ILhs, typename IRhs>
- [[nodiscard]] bool operator>=(const dense_map_iterator<ILhs> &lhs, const dense_map_iterator<IRhs> &rhs) ENTT_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;
- dense_map_local_iterator() ENTT_NOEXCEPT
- : it{},
- offset{} {}
- dense_map_local_iterator(It iter, const std::size_t pos) ENTT_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>>>
- dense_map_local_iterator(const dense_map_local_iterator<Other> &other) ENTT_NOEXCEPT
- : it{other.it},
- offset{other.offset} {}
- dense_map_local_iterator &operator++() ENTT_NOEXCEPT {
- return offset = it[offset].next, *this;
- }
- dense_map_local_iterator operator++(int) ENTT_NOEXCEPT {
- dense_map_local_iterator orig = *this;
- return ++(*this), orig;
- }
- [[nodiscard]] pointer operator->() const ENTT_NOEXCEPT {
- return operator*();
- }
- [[nodiscard]] reference operator*() const ENTT_NOEXCEPT {
- return {it[offset].element.first, it[offset].element.second};
- }
- [[nodiscard]] std::size_t index() const ENTT_NOEXCEPT {
- return offset;
- }
- private:
- It it;
- std::size_t offset;
- };
- template<typename ILhs, typename IRhs>
- [[nodiscard]] bool operator==(const dense_map_local_iterator<ILhs> &lhs, const dense_map_local_iterator<IRhs> &rhs) ENTT_NOEXCEPT {
- return lhs.index() == rhs.index();
- }
- template<typename ILhs, typename IRhs>
- [[nodiscard]] bool operator!=(const dense_map_local_iterator<ILhs> &lhs, const dense_map_local_iterator<IRhs> &rhs) ENTT_NOEXCEPT {
- return !(lhs == rhs);
- }
- } // namespace internal
- /**
- * Internal details not to be documented.
- * @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;
- using node_type = internal::dense_map_node<Key, Type>;
- using alloc_traits = typename 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 ENTT_NOEXCEPT {
- return fast_mod(sparse.second()(key), bucket_count());
- }
- template<typename Other>
- [[nodiscard]] auto constrained_find(const Other &key, std::size_t bucket) {
- for(auto it = begin(bucket), last = end(bucket); it != last; ++it) {
- if(packed.second()(it->first, key)) {
- return begin() + static_cast<typename iterator::difference_type>(it.index());
- }
- }
- return end();
- }
- template<typename Other>
- [[nodiscard]] auto constrained_find(const Other &key, std::size_t bucket) const {
- for(auto it = cbegin(bucket), last = cend(bucket); it != last; ++it) {
- if(packed.second()(it->first, key)) {
- return cbegin() + static_cast<typename iterator::difference_type>(it.index());
- }
- }
- 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) {
- packed.first()[pos] = std::move(packed.first().back());
- size_type *curr = sparse.first().data() + key_to_bucket(packed.first().back().element.first);
- for(; *curr != last; curr = &packed.first()[*curr].next) {}
- *curr = pos;
- }
- packed.first().pop_back();
- }
- void rehash_if_required() {
- if(size() > (bucket_count() * max_load_factor())) {
- rehash(bucket_count() * 2u);
- }
- }
- public:
- /*! @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 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 Allocator type. */
- using allocator_type = Allocator;
- /*! @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 bucket_count Minimal number of buckets.
- * @param allocator The allocator to use.
- */
- dense_map(const size_type bucket_count, const allocator_type &allocator)
- : dense_map{bucket_count, hasher{}, key_equal{}, allocator} {}
- /**
- * @brief Constructs an empty container with a given allocator, hash
- * function and user supplied minimal number of buckets.
- * @param bucket_count Minimal number of buckets.
- * @param hash Hash function to use.
- * @param allocator The allocator to use.
- */
- dense_map(const size_type bucket_count, const hasher &hash, const allocator_type &allocator)
- : dense_map{bucket_count, 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 bucket_count 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 bucket_count, const hasher &hash = hasher{}, const key_equal &equal = key_equal{}, const allocator_type &allocator = allocator_type{})
- : sparse{allocator, hash},
- packed{allocator, equal},
- threshold{default_threshold} {
- rehash(bucket_count);
- }
- /*! @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 &&) = 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 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 &&) = default;
- /**
- * @brief Returns the associated allocator.
- * @return The associated allocator.
- */
- [[nodiscard]] constexpr allocator_type get_allocator() const ENTT_NOEXCEPT {
- return sparse.first().get_allocator();
- }
- /**
- * @brief Returns an iterator to the beginning.
- *
- * The returned iterator points to the first instance of the internal array.
- * 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 ENTT_NOEXCEPT {
- return packed.first().begin();
- }
- /*! @copydoc cbegin */
- [[nodiscard]] const_iterator begin() const ENTT_NOEXCEPT {
- return cbegin();
- }
- /*! @copydoc begin */
- [[nodiscard]] iterator begin() ENTT_NOEXCEPT {
- return packed.first().begin();
- }
- /**
- * @brief Returns an iterator to the end.
- *
- * The returned iterator points to the element following the last instance
- * of the internal array. Attempting to dereference the returned iterator
- * results in undefined behavior.
- *
- * @return An iterator to the element following the last instance of the
- * internal array.
- */
- [[nodiscard]] const_iterator cend() const ENTT_NOEXCEPT {
- return packed.first().end();
- }
- /*! @copydoc cend */
- [[nodiscard]] const_iterator end() const ENTT_NOEXCEPT {
- return cend();
- }
- /*! @copydoc end */
- [[nodiscard]] iterator end() ENTT_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 ENTT_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 ENTT_NOEXCEPT {
- return packed.first().size();
- }
- /*! @brief Clears the container. */
- void clear() ENTT_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()[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().data() + key_to_bucket(key); *curr != (std::numeric_limits<size_type>::max)(); 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 Exchanges the contents with those of a given container.
- * @param other Container to exchange the content with.
- */
- void swap(dense_map &other) {
- using std::swap;
- swap(sparse, other.sparse);
- swap(packed, other.packed);
- swap(threshold, other.threshold);
- }
- /**
- * @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 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 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
- * 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 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 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 {packed.first().begin(), (std::numeric_limits<size_type>::max)()};
- }
- /**
- * @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([[maybe_unused]] 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 {packed.first().begin(), (std::numeric_limits<size_type>::max)()};
- }
- /**
- * @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 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 count New number of buckets.
- */
- void rehash(const size_type count) {
- auto value = (std::max)(count, minimum_capacity);
- value = (std::max)(value, static_cast<size_type>(size() / max_load_factor()));
- if(const auto sz = next_power_of_two(value); sz != bucket_count()) {
- sparse.first().resize(sz);
- std::fill(sparse.first().begin(), sparse.first().end(), (std::numeric_limits<size_type>::max)());
- 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 count New number of elements.
- */
- void reserve(const size_type count) {
- packed.first().reserve(count);
- rehash(static_cast<size_type>(std::ceil(count / 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;
- };
- } // namespace entt
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- 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
- /**
- * Internal details not to be documented.
- * @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 "../config/config.h"
- // #include "type_traits.hpp"
- #ifndef ENTT_CORE_TYPE_TRAITS_HPP
- #define ENTT_CORE_TYPE_TRAITS_HPP
- #include <cstddef>
- #include <iterator>
- #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.
- * @tparam The size of the type if `sizeof` accepts it, 0 otherwise.
- */
- 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))>>
- : 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 Type First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<std::size_t Index, typename Type, typename... Other>
- struct type_list_element<Index, type_list<Type, Other...>>
- : type_list_element<Index - 1u, type_list<Other...>> {};
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam Type First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<typename Type, typename... Other>
- struct type_list_element<0u, type_list<Type, Other...>> {
- /*! @brief Searched type. */
- using type = Type;
- };
- /**
- * @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 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;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename>
- struct type_list_unique;
- /**
- * @brief Removes duplicates types from a type list.
- * @tparam Type One of the types provided by the given type list.
- * @tparam Other The other types provided by the given type list.
- */
- template<typename Type, typename... Other>
- struct type_list_unique<type_list<Type, Other...>> {
- /*! @brief A type list without duplicate types. */
- using type = std::conditional_t<
- (std::is_same_v<Type, Other> || ...),
- typename type_list_unique<type_list<Other...>>::type,
- type_list_cat_t<type_list<Type>, typename type_list_unique<type_list<Other...>>::type>>;
- };
- /*! @brief Removes duplicates types from a type list. */
- template<>
- struct type_list_unique<type_list<>> {
- /*! @brief A type list without duplicate types. */
- using type = type_list<>;
- };
- /**
- * @brief Helper type.
- * @tparam Type A type list.
- */
- template<typename Type>
- using type_list_unique_t = typename type_list_unique<Type>::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::disjunction<std::is_same<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 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 value. */
- static constexpr auto value = Value;
- };
- /**
- * @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 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 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
- * Internal details not to be documented.
- */
- 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
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /*! @copydoc is_iterator */
- template<typename Type>
- struct is_iterator<Type, std::enable_if_t<!std::is_same_v<std::remove_const_t<std::remove_pointer_t<Type>>, void>>>
- : 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::conjunction<std::is_empty<Type>, std::negation<std::is_final<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;
- /**
- * @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, typename = void>
- struct is_equality_comparable: std::false_type {};
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- 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 Type, std::size_t... Index>
- [[nodiscard]] constexpr bool unpack_maybe_equality_comparable(std::index_sequence<Index...>) {
- return (is_equality_comparable<std::tuple_element_t<Index, Type>>::value && ...);
- }
- template<typename>
- [[nodiscard]] constexpr bool maybe_equality_comparable(choice_t<0>) {
- return true;
- }
- template<typename Type>
- [[nodiscard]] constexpr auto maybe_equality_comparable(choice_t<1>) -> decltype(std::declval<typename Type::value_type>(), bool{}) {
- if constexpr(is_iterator_v<Type>) {
- return true;
- } else if constexpr(std::is_same_v<typename Type::value_type, Type>) {
- return maybe_equality_comparable<Type>(choice<0>);
- } else {
- return is_equality_comparable<typename Type::value_type>::value;
- }
- }
- template<typename Type>
- [[nodiscard]] constexpr std::enable_if_t<is_complete_v<std::tuple_size<std::remove_const_t<Type>>>, bool> maybe_equality_comparable(choice_t<2>) {
- if constexpr(has_tuple_size_value<Type>::value) {
- return unpack_maybe_equality_comparable<Type>(std::make_index_sequence<std::tuple_size<Type>::value>{});
- } else {
- return maybe_equality_comparable<Type>(choice<1>);
- }
- }
- } // namespace internal
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /*! @copydoc is_equality_comparable */
- template<typename Type>
- struct is_equality_comparable<Type, std::void_t<decltype(std::declval<Type>() == std::declval<Type>())>>
- : std::bool_constant<internal::maybe_equality_comparable<Type>(choice<2>)> {};
- /**
- * @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 = std::add_const_t<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;
- } // namespace entt
- #endif
- namespace entt {
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- namespace internal {
- template<typename Type, std::size_t, typename = void>
- struct compressed_pair_element {
- using reference = Type &;
- using const_reference = const Type &;
- template<bool Dummy = true, typename = std::enable_if_t<Dummy && std::is_default_constructible_v<Type>>>
- compressed_pair_element()
- : value{} {}
- template<typename Args, typename = std::enable_if_t<!std::is_same_v<std::remove_cv_t<std::remove_reference_t<Args>>, compressed_pair_element>>>
- compressed_pair_element(Args &&args)
- : value{std::forward<Args>(args)} {}
- template<typename... Args, std::size_t... Index>
- compressed_pair_element(std::tuple<Args...> args, std::index_sequence<Index...>)
- : value{std::forward<Args>(std::get<Index>(args))...} {}
- [[nodiscard]] reference get() ENTT_NOEXCEPT {
- return value;
- }
- [[nodiscard]] const_reference get() const ENTT_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<bool Dummy = true, typename = std::enable_if_t<Dummy && std::is_default_constructible_v<base_type>>>
- compressed_pair_element()
- : base_type{} {}
- template<typename Args, typename = std::enable_if_t<!std::is_same_v<std::remove_cv_t<std::remove_reference_t<Args>>, compressed_pair_element>>>
- compressed_pair_element(Args &&args)
- : base_type{std::forward<Args>(args)} {}
- template<typename... Args, std::size_t... Index>
- compressed_pair_element(std::tuple<Args...> args, std::index_sequence<Index...>)
- : base_type{std::forward<Args>(std::get<Index>(args))...} {}
- [[nodiscard]] reference get() ENTT_NOEXCEPT {
- return *this;
- }
- [[nodiscard]] const_reference get() const ENTT_NOEXCEPT {
- return *this;
- }
- };
- } // namespace internal
- /**
- * Internal details not to be documented.
- * @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()
- : 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) = 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)
- : 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)
- : first_base{std::move(args), std::index_sequence_for<Args...>{}},
- second_base{std::move(other), std::index_sequence_for<Other...>{}} {}
- /**
- * @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) = default;
- /**
- * @brief Returns the first element that a pair stores.
- * @return The first element that a pair stores.
- */
- [[nodiscard]] first_type &first() ENTT_NOEXCEPT {
- return static_cast<first_base &>(*this).get();
- }
- /*! @copydoc first */
- [[nodiscard]] const first_type &first() const ENTT_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]] second_type &second() ENTT_NOEXCEPT {
- return static_cast<second_base &>(*this).get();
- }
- /*! @copydoc second */
- [[nodiscard]] const second_type &second() const ENTT_NOEXCEPT {
- return static_cast<const second_base &>(*this).get();
- }
- /**
- * @brief Swaps two compressed pair objects.
- * @param other The compressed pair to swap with.
- */
- void swap(compressed_pair &other) {
- 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>
- decltype(auto) get() ENTT_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>
- decltype(auto) get() const ENTT_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>
- inline void swap(compressed_pair<First, Second> &lhs, compressed_pair<First, Second> &rhs) {
- lhs.swap(rhs);
- }
- } // namespace entt
- // disable structured binding support for clang 6, it messes when specializing tuple_size
- #if !defined __clang_major__ || __clang_major__ > 6
- 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
- #endif
- // #include "../core/fwd.hpp"
- #ifndef ENTT_CORE_FWD_HPP
- #define ENTT_CORE_FWD_HPP
- #include <cstdint>
- #include <type_traits>
- // #include "../config/config.h"
- namespace entt {
- template<std::size_t Len = sizeof(double[2]), std::size_t = alignof(typename std::aligned_storage_t<Len + !Len>)>
- 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<>;
- } // 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 "../core/attribute.h"
- #ifndef ENTT_CORE_ATTRIBUTE_H
- #define ENTT_CORE_ATTRIBUTE_H
- #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
- #endif
- // #include "fwd.hpp"
- // #include "hashed_string.hpp"
- #ifndef ENTT_CORE_HASHED_STRING_HPP
- #define ENTT_CORE_HASHED_STRING_HPP
- #include <cstddef>
- #include <cstdint>
- // #include "../config/config.h"
- // #include "fwd.hpp"
- namespace entt {
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- namespace internal {
- template<typename>
- struct fnv1a_traits;
- template<>
- struct fnv1a_traits<std::uint32_t> {
- using type = std::uint32_t;
- static constexpr std::uint32_t offset = 2166136261;
- static constexpr std::uint32_t prime = 16777619;
- };
- template<>
- struct fnv1a_traits<std::uint64_t> {
- using type = std::uint64_t;
- static constexpr std::uint64_t offset = 14695981039346656037ull;
- static constexpr std::uint64_t 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;
- size_type length;
- hash_type hash;
- };
- } // namespace internal
- /**
- * Internal details not to be documented.
- * @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 hs_traits = internal::fnv1a_traits<id_type>;
- struct const_wrapper {
- // non-explicit constructor on purpose
- constexpr const_wrapper(const Char *str) ENTT_NOEXCEPT: repr{str} {}
- const Char *repr;
- };
- // Fowler–Noll–Vo hash function v. 1a - the good
- [[nodiscard]] static constexpr auto helper(const Char *str) ENTT_NOEXCEPT {
- base_type base{str, 0u, hs_traits::offset};
- for(; str[base.length]; ++base.length) {
- base.hash = (base.hash ^ static_cast<hs_traits::type>(str[base.length])) * hs_traits::prime;
- }
- return base;
- }
- // Fowler–Noll–Vo hash function v. 1a - the good
- [[nodiscard]] static constexpr auto helper(const Char *str, const std::size_t len) ENTT_NOEXCEPT {
- base_type base{str, len, hs_traits::offset};
- for(size_type pos{}; pos < len; ++pos) {
- base.hash = (base.hash ^ static_cast<hs_traits::type>(str[pos])) * hs_traits::prime;
- }
- return base;
- }
- 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) ENTT_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>
- [[nodiscard]] static constexpr hash_type value(const value_type (&str)[N]) ENTT_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) ENTT_NOEXCEPT {
- return basic_hashed_string{wrapper};
- }
- /*! @brief Constructs an empty hashed string. */
- constexpr basic_hashed_string() ENTT_NOEXCEPT
- : base_type{} {}
- /**
- * @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) ENTT_NOEXCEPT
- : base_type{helper(str, len)} {}
- /**
- * @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>
- constexpr basic_hashed_string(const value_type (&str)[N]) ENTT_NOEXCEPT
- : base_type{helper(str)} {}
- /**
- * @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) ENTT_NOEXCEPT
- : base_type{helper(wrapper.repr)} {}
- /**
- * @brief Returns the size a hashed string.
- * @return The size of the hashed string.
- */
- [[nodiscard]] constexpr size_type size() const ENTT_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 ENTT_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 ENTT_NOEXCEPT {
- return base_type::hash;
- }
- /*! @copydoc data */
- [[nodiscard]] constexpr operator const value_type *() const ENTT_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 ENTT_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, const 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>
- 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) ENTT_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) ENTT_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) ENTT_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) ENTT_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) ENTT_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) ENTT_NOEXCEPT {
- return !(lhs < rhs);
- }
- /*! @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>;
- inline namespace literals {
- /**
- * @brief User defined literal for hashed strings.
- * @param str The literal without its suffix.
- * @return A properly initialized hashed string.
- */
- [[nodiscard]] constexpr hashed_string operator"" _hs(const char *str, std::size_t) ENTT_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]] constexpr hashed_wstring operator"" _hws(const wchar_t *str, std::size_t) ENTT_NOEXCEPT {
- return hashed_wstring{str};
- }
- } // namespace literals
- } // namespace entt
- #endif
- namespace entt {
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- namespace internal {
- struct ENTT_API type_index final {
- [[nodiscard]] static id_type next() ENTT_NOEXCEPT {
- static ENTT_MAYBE_ATOMIC(id_type) value{};
- return value++;
- }
- };
- template<typename Type>
- [[nodiscard]] constexpr auto stripped_type_name() ENTT_NOEXCEPT {
- #if defined ENTT_PRETTY_FUNCTION
- std::string_view pretty_function{ENTT_PRETTY_FUNCTION};
- auto first = pretty_function.find_first_not_of(' ', pretty_function.find_first_of(ENTT_PRETTY_FUNCTION_PREFIX) + 1);
- auto value = pretty_function.substr(first, pretty_function.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]] static constexpr std::string_view type_name(int) ENTT_NOEXCEPT {
- constexpr auto value = stripped_type_name<Type>();
- return value;
- }
- template<typename Type>
- [[nodiscard]] static std::string_view type_name(char) ENTT_NOEXCEPT {
- static const auto value = stripped_type_name<Type>();
- return value;
- }
- template<typename Type, auto = stripped_type_name<Type>().find_first_of('.')>
- [[nodiscard]] static constexpr id_type type_hash(int) ENTT_NOEXCEPT {
- constexpr auto stripped = stripped_type_name<Type>();
- constexpr auto value = hashed_string::value(stripped.data(), stripped.size());
- return value;
- }
- template<typename Type>
- [[nodiscard]] static id_type type_hash(char) ENTT_NOEXCEPT {
- static const auto value = [](const auto stripped) {
- return hashed_string::value(stripped.data(), stripped.size());
- }(stripped_type_name<Type>());
- return value;
- }
- } // namespace internal
- /**
- * Internal details not to be documented.
- * @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() ENTT_NOEXCEPT {
- static const id_type value = internal::type_index::next();
- return value;
- }
- /*! @copydoc value */
- [[nodiscard]] constexpr operator id_type() const ENTT_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() ENTT_NOEXCEPT {
- return internal::type_hash<Type>(0);
- #else
- [[nodiscard]] static constexpr id_type value() ENTT_NOEXCEPT {
- return type_index<Type>::value();
- #endif
- }
- /*! @copydoc value */
- [[nodiscard]] constexpr operator id_type() const ENTT_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() ENTT_NOEXCEPT {
- return internal::type_name<Type>(0);
- }
- /*! @copydoc value */
- [[nodiscard]] constexpr operator std::string_view() const ENTT_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>
- constexpr type_info(std::in_place_type_t<Type>) ENTT_NOEXCEPT
- : seq{type_index<std::remove_cv_t<std::remove_reference_t<Type>>>::value()},
- identifier{type_hash<std::remove_cv_t<std::remove_reference_t<Type>>>::value()},
- alias{type_name<std::remove_cv_t<std::remove_reference_t<Type>>>::value()} {}
- /**
- * @brief Type index.
- * @return Type index.
- */
- [[nodiscard]] constexpr id_type index() const ENTT_NOEXCEPT {
- return seq;
- }
- /**
- * @brief Type hash.
- * @return Type hash.
- */
- [[nodiscard]] constexpr id_type hash() const ENTT_NOEXCEPT {
- return identifier;
- }
- /**
- * @brief Type name.
- * @return Type name.
- */
- [[nodiscard]] constexpr std::string_view name() const ENTT_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]] inline constexpr bool operator==(const type_info &lhs, const type_info &rhs) ENTT_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]] inline constexpr bool operator!=(const type_info &lhs, const type_info &rhs) ENTT_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) ENTT_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) ENTT_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) ENTT_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) ENTT_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() ENTT_NOEXCEPT {
- if constexpr(std::is_same_v<Type, std::remove_cv_t<std::remove_reference_t<Type>>>) {
- static type_info instance{std::in_place_type<Type>};
- return instance;
- } else {
- return type_id<std::remove_cv_t<std::remove_reference_t<Type>>>();
- }
- }
- /*! @copydoc type_id */
- template<typename Type>
- [[nodiscard]] const type_info &type_id(Type &&) ENTT_NOEXCEPT {
- return type_id<std::remove_cv_t<std::remove_reference_t<Type>>>();
- }
- } // namespace entt
- #endif
- // #include "../core/utility.hpp"
- #ifndef ENTT_CORE_UTILITY_HPP
- #define ENTT_CORE_UTILITY_HPP
- #include <utility>
- // #include "../config/config.h"
- 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<class Type>
- [[nodiscard]] constexpr Type &&operator()(Type &&value) const ENTT_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) ENTT_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) ENTT_NOEXCEPT {
- return func;
- }
- /**
- * @brief Helper type for visitors.
- * @tparam Func Types of function objects.
- */
- template<class... Func>
- struct overloaded: Func... {
- using Func::operator()...;
- };
- /**
- * @brief Deduction guide.
- * @tparam Func Types of function objects.
- */
- template<class... Func>
- overloaded(Func...) -> overloaded<Func...>;
- /**
- * @brief Basic implementation of a y-combinator.
- * @tparam Func Type of a potentially recursive function.
- */
- template<class Func>
- struct y_combinator {
- /**
- * @brief Constructs a y-combinator from a given function.
- * @param recursive A potentially recursive function.
- */
- y_combinator(Func recursive)
- : 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<class... Args>
- decltype(auto) operator()(Args &&...args) const {
- return func(*this, std::forward<Args>(args)...);
- }
- /*! @copydoc operator()() */
- template<class... Args>
- decltype(auto) operator()(Args &&...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 <algorithm>
- #include <functional>
- #include <type_traits>
- #include <utility>
- #include <vector>
- // #include "../config/config.h"
- // #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
- * Internal details not to be documented.
- */
- namespace internal {
- template<typename Ret, typename... Args>
- auto function_pointer(Ret (*)(Args...)) -> Ret (*)(Args...);
- template<typename Ret, typename Type, typename... Args, typename Other>
- auto function_pointer(Ret (*)(Type, Args...), Other &&) -> Ret (*)(Args...);
- template<typename Class, typename Ret, typename... Args, typename... Other>
- auto function_pointer(Ret (Class::*)(Args...), Other &&...) -> Ret (*)(Args...);
- template<typename Class, typename Ret, typename... Args, typename... Other>
- auto function_pointer(Ret (Class::*)(Args...) const, Other &&...) -> Ret (*)(Args...);
- template<typename Class, typename Type, typename... Other>
- auto function_pointer(Type Class::*, Other &&...) -> Type (*)();
- template<typename... Type>
- using function_pointer_t = decltype(internal::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
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /*! @brief Used to wrap a function or a member of a specified type. */
- template<auto>
- struct connect_arg_t {};
- /*! @brief Constant of type connect_arg_t used to disambiguate calls. */
- template<auto Func>
- inline constexpr connect_arg_t<Func> connect_arg{};
- /**
- * @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...)> {
- template<auto Candidate, std::size_t... Index>
- [[nodiscard]] auto wrap(std::index_sequence<Index...>) ENTT_NOEXCEPT {
- return [](const void *, Args... args) -> Ret {
- [[maybe_unused]] const auto arguments = std::forward_as_tuple(std::forward<Args>(args)...);
- return static_cast<Ret>(std::invoke(Candidate, std::forward<type_list_element_t<Index, type_list<Args...>>>(std::get<Index>(arguments))...));
- };
- }
- template<auto Candidate, typename Type, std::size_t... Index>
- [[nodiscard]] auto wrap(Type &, std::index_sequence<Index...>) ENTT_NOEXCEPT {
- return [](const void *payload, Args... args) -> Ret {
- [[maybe_unused]] const auto arguments = std::forward_as_tuple(std::forward<Args>(args)...);
- Type *curr = static_cast<Type *>(const_cast<constness_as_t<void, Type> *>(payload));
- return static_cast<Ret>(std::invoke(Candidate, *curr, std::forward<type_list_element_t<Index, type_list<Args...>>>(std::get<Index>(arguments))...));
- };
- }
- template<auto Candidate, typename Type, std::size_t... Index>
- [[nodiscard]] auto wrap(Type *, std::index_sequence<Index...>) ENTT_NOEXCEPT {
- return [](const void *payload, Args... args) -> Ret {
- [[maybe_unused]] const auto arguments = std::forward_as_tuple(std::forward<Args>(args)...);
- Type *curr = static_cast<Type *>(const_cast<constness_as_t<void, Type> *>(payload));
- return static_cast<Ret>(std::invoke(Candidate, curr, std::forward<type_list_element_t<Index, type_list<Args...>>>(std::get<Index>(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() ENTT_NOEXCEPT
- : instance{nullptr},
- fn{nullptr} {}
- /**
- * @brief Constructs a delegate and connects a free function or an unbound
- * member.
- * @tparam Candidate Function or member to connect to the delegate.
- */
- template<auto Candidate>
- delegate(connect_arg_t<Candidate>) ENTT_NOEXCEPT {
- connect<Candidate>();
- }
- /**
- * @brief Constructs a delegate and connects a free function with payload or
- * a bound member.
- * @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 object that fits the purpose.
- */
- template<auto Candidate, typename Type>
- delegate(connect_arg_t<Candidate>, Type &&value_or_instance) ENTT_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) ENTT_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() ENTT_NOEXCEPT {
- instance = nullptr;
- if constexpr(std::is_invocable_r_v<Ret, decltype(Candidate), Args...>) {
- fn = [](const void *, Args... args) -> Ret {
- 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) ENTT_NOEXCEPT {
- instance = &value_or_instance;
- if constexpr(std::is_invocable_r_v<Ret, decltype(Candidate), Type &, Args...>) {
- fn = [](const void *payload, Args... args) -> Ret {
- 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) ENTT_NOEXCEPT {
- instance = value_or_instance;
- if constexpr(std::is_invocable_r_v<Ret, decltype(Candidate), Type *, Args...>) {
- fn = [](const void *payload, Args... args) -> Ret {
- 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) ENTT_NOEXCEPT {
- instance = payload;
- fn = function;
- }
- /**
- * @brief Resets a delegate.
- *
- * After a reset, a delegate cannot be invoked anymore.
- */
- void reset() ENTT_NOEXCEPT {
- instance = nullptr;
- fn = nullptr;
- }
- /**
- * @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 ENTT_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 ENTT_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 ENTT_NOEXCEPT {
- return fn == other.fn && instance == other.instance;
- }
- private:
- const void *instance;
- function_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) ENTT_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> {
- /*! @brief A sink is allowed to modify a signal. */
- friend class sink<sigh<Ret(Args...), Allocator>>;
- using alloc_traits = std::allocator_traits<Allocator>;
- static_assert(std::is_same_v<typename alloc_traits::value_type, Ret (*)(Args...)>, "Invalid value type");
- using container_type = std::vector<delegate<Ret(Args...)>, typename alloc_traits::template rebind_alloc<delegate<Ret(Args...)>>>;
- 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()
- : sigh{allocator_type{}} {}
- /**
- * @brief Constructs a signal handler with a given allocator.
- * @param allocator The allocator to use.
- */
- explicit sigh(const allocator_type &allocator)
- : 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) ENTT_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) ENTT_NOEXCEPT
- : calls{std::move(other.calls), allocator} {}
- /**
- * @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) ENTT_NOEXCEPT {
- calls = std::move(other.calls);
- 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) {
- using std::swap;
- swap(calls, other.calls);
- }
- /**
- * @brief Returns the associated allocator.
- * @return The associated allocator.
- */
- [[nodiscard]] constexpr allocator_type get_allocator() const ENTT_NOEXCEPT {
- return calls.get_allocator();
- }
- /**
- * @brief Instance type when it comes to connecting member functions.
- * @tparam Class Type of class to which the member function belongs.
- */
- template<typename Class>
- using instance_type = Class *;
- /**
- * @brief Number of listeners connected to the signal.
- * @return Number of listeners currently connected.
- */
- [[nodiscard]] size_type size() const ENTT_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 ENTT_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 &&call: std::as_const(calls)) {
- call(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 &&call: calls) {
- if constexpr(std::is_void_v<Ret>) {
- if constexpr(std::is_invocable_r_v<bool, Func>) {
- call(args...);
- if(func()) { break; }
- } else {
- call(args...);
- func();
- }
- } else {
- if constexpr(std::is_invocable_r_v<bool, Func, Ret>) {
- if(func(call(args...))) { break; }
- } else {
- func(call(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 {
- /*! @brief A sink is allowed to create connection objects. */
- template<typename>
- friend class sink;
- connection(delegate<void(void *)> fn, void *ref)
- : disconnect{fn}, signal{ref} {}
- public:
- /*! @brief Default constructor. */
- connection() = default;
- /**
- * @brief Checks whether a connection is properly initialized.
- * @return True if the connection is properly initialized, false otherwise.
- */
- [[nodiscard]] explicit operator bool() const ENTT_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) ENTT_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) ENTT_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 = std::move(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 ENTT_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 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>();
- }
- public:
- /**
- * @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) ENTT_NOEXCEPT
- : offset{},
- 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 ENTT_NOEXCEPT {
- return signal->calls.empty();
- }
- /**
- * @brief Returns a sink that connects before a given free function or an
- * unbound member.
- * @tparam Function A valid free function pointer.
- * @return A properly initialized sink object.
- */
- template<auto Function>
- [[nodiscard]] sink before() {
- delegate<Ret(Args...)> call{};
- call.template connect<Function>();
- const auto &calls = signal->calls;
- const auto it = std::find(calls.cbegin(), calls.cend(), std::move(call));
- sink other{*this};
- other.offset = calls.cend() - it;
- return other;
- }
- /**
- * @brief Returns a sink that connects before a free function with payload
- * or a bound member.
- * @tparam Candidate Member or free function to look for.
- * @tparam Type Type of class or type of payload.
- * @param value_or_instance A valid object that fits the purpose.
- * @return A properly initialized sink object.
- */
- template<auto Candidate, typename Type>
- [[nodiscard]] sink before(Type &&value_or_instance) {
- delegate<Ret(Args...)> call{};
- call.template connect<Candidate>(value_or_instance);
- const auto &calls = signal->calls;
- const auto it = std::find(calls.cbegin(), calls.cend(), std::move(call));
- sink other{*this};
- other.offset = calls.cend() - it;
- return other;
- }
- /**
- * @brief Returns a sink that connects before a given instance or specific
- * payload.
- * @tparam Type Type of class or type of payload.
- * @param value_or_instance A valid object that fits the purpose.
- * @return A properly initialized sink object.
- */
- template<typename Type>
- [[nodiscard]] sink before(Type &value_or_instance) {
- return before(&value_or_instance);
- }
- /**
- * @brief Returns a sink that connects before a given instance or specific
- * payload.
- * @tparam Type Type of class or type of payload.
- * @param value_or_instance A valid pointer that fits the purpose.
- * @return A properly initialized sink object.
- */
- template<typename Type>
- [[nodiscard]] sink before(Type *value_or_instance) {
- sink other{*this};
- if(value_or_instance) {
- const auto &calls = signal->calls;
- const auto it = std::find_if(calls.cbegin(), calls.cend(), [value_or_instance](const auto &delegate) {
- return delegate.data() == value_or_instance;
- });
- other.offset = calls.cend() - it;
- }
- return other;
- }
- /**
- * @brief Returns a sink that connects before anything else.
- * @return A properly initialized sink object.
- */
- [[nodiscard]] sink before() {
- sink other{*this};
- other.offset = signal->calls.size();
- return other;
- }
- /**
- * @brief Connects a free function or an unbound member to a signal.
- *
- * The signal handler performs checks to avoid multiple connections for the
- * same function.
- *
- * @tparam Candidate Function or member to connect to the signal.
- * @return A properly initialized connection object.
- */
- template<auto Candidate>
- connection connect() {
- disconnect<Candidate>();
- delegate<Ret(Args...)> call{};
- call.template connect<Candidate>();
- signal->calls.insert(signal->calls.end() - offset, std::move(call));
- delegate<void(void *)> conn{};
- conn.template connect<&release<Candidate>>();
- return {std::move(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. On the other side, the signal handler performs
- * checks to avoid multiple connections for the same function.<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 object 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<Ret(Args...)> call{};
- call.template connect<Candidate>(value_or_instance);
- signal->calls.insert(signal->calls.end() - offset, std::move(call));
- delegate<void(void *)> conn{};
- conn.template connect<&release<Candidate, Type>>(value_or_instance);
- return {std::move(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() {
- auto &calls = signal->calls;
- delegate<Ret(Args...)> call{};
- call.template connect<Candidate>();
- calls.erase(std::remove(calls.begin(), calls.end(), std::move(call)), calls.end());
- }
- /**
- * @brief Disconnects a free function with payload or a bound member from a
- * signal.
- * @tparam Candidate Function or member to disconnect from the signal.
- * @tparam Type Type of class or type of payload.
- * @param value_or_instance A valid object that fits the purpose.
- */
- template<auto Candidate, typename Type>
- void disconnect(Type &&value_or_instance) {
- auto &calls = signal->calls;
- delegate<Ret(Args...)> call{};
- call.template connect<Candidate>(value_or_instance);
- calls.erase(std::remove(calls.begin(), calls.end(), std::move(call)), calls.end());
- }
- /**
- * @brief Disconnects free functions with payload or bound members from a
- * signal.
- * @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 Disconnects free functions with payload or bound members from a
- * signal.
- * @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) {
- if(value_or_instance) {
- auto &calls = signal->calls;
- auto predicate = [value_or_instance](const auto &delegate) { return delegate.data() == value_or_instance; };
- calls.erase(std::remove_if(calls.begin(), calls.end(), std::move(predicate)), calls.end());
- }
- }
- /*! @brief Disconnects all the listeners from a signal. */
- void disconnect() {
- signal->calls.clear();
- }
- private:
- difference_type offset;
- 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
- * Internal details not to be documented.
- */
- namespace internal {
- struct basic_dispatcher_handler {
- virtual ~basic_dispatcher_handler() = default;
- virtual void publish() = 0;
- virtual void disconnect(void *) = 0;
- virtual void clear() ENTT_NOEXCEPT = 0;
- virtual std::size_t size() const ENTT_NOEXCEPT = 0;
- };
- template<typename Event, typename Allocator>
- class dispatcher_handler final: public basic_dispatcher_handler {
- static_assert(std::is_same_v<Event, std::decay_t<Event>>, "Invalid event type");
- using alloc_traits = std::allocator_traits<Allocator>;
- using signal_type = sigh<void(Event &), typename alloc_traits::template rebind_alloc<void (*)(Event &)>>;
- using container_type = std::vector<Event, typename alloc_traits::template rebind_alloc<Event>>;
- 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() + length);
- }
- void disconnect(void *instance) override {
- bucket().disconnect(instance);
- }
- void clear() ENTT_NOEXCEPT override {
- events.clear();
- }
- [[nodiscard]] auto bucket() ENTT_NOEXCEPT {
- using sink_type = typename sigh<void(Event &)>::sink_type;
- return sink_type{signal};
- }
- void trigger(Event event) {
- signal.publish(event);
- }
- template<typename... Args>
- void enqueue(Args &&...args) {
- if constexpr(std::is_aggregate_v<Event>) {
- events.push_back(Event{std::forward<Args>(args)...});
- } else {
- events.emplace_back(std::forward<Args>(args)...);
- }
- }
- std::size_t size() const ENTT_NOEXCEPT override {
- return events.size();
- }
- private:
- signal_type signal;
- container_type events;
- };
- } // namespace internal
- /**
- * Internal details not to be documented.
- * @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 `Event`, listeners are such that they can be invoked with an argument of
- * type `Event &`, 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 Event>
- using handler_type = internal::dispatcher_handler<Event, Allocator>;
- using key_type = id_type;
- // std::shared_ptr because of its type erased allocator which is pretty 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<id_type, mapped_type, identity, std::equal_to<id_type>, container_allocator>;
- template<typename Event>
- [[nodiscard]] handler_type<Event> &assure(const id_type id) {
- auto &&ptr = pools.first()[id];
- if(!ptr) {
- const auto &allocator = pools.second();
- ptr = std::allocate_shared<handler_type<Event>>(allocator, allocator);
- }
- return static_cast<handler_type<Event> &>(*ptr);
- }
- template<typename Event>
- [[nodiscard]] const handler_type<Event> *assure(const id_type id) const {
- auto &container = pools.first();
- if(const auto it = container.find(id); it != container.end()) {
- return static_cast<const handler_type<Event> *>(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 Move constructor.
- * @param other The instance to move from.
- */
- basic_dispatcher(basic_dispatcher &&other) ENTT_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) ENTT_NOEXCEPT
- : pools{container_type{std::move(other.pools.first()), allocator}, allocator} {}
- /**
- * @brief Move assignment operator.
- * @param other The instance to move from.
- * @return This dispatcher.
- */
- basic_dispatcher &operator=(basic_dispatcher &&other) ENTT_NOEXCEPT {
- pools = std::move(other.pools);
- 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) {
- using std::swap;
- swap(pools, other.pools);
- }
- /**
- * @brief Returns the associated allocator.
- * @return The associated allocator.
- */
- [[nodiscard]] constexpr allocator_type get_allocator() const ENTT_NOEXCEPT {
- return pools.second();
- }
- /**
- * @brief Returns the number of pending events for a given type.
- * @tparam Event 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 Event>
- size_type size(const id_type id = type_hash<Event>::value()) const ENTT_NOEXCEPT {
- const auto *cpool = assure<Event>(id);
- return cpool ? cpool->size() : 0u;
- }
- /**
- * @brief Returns the total number of pending events.
- * @return The total number of pending events.
- */
- size_type size() const ENTT_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(Event &);
- * @endcode
- *
- * The order of invocation of the listeners isn't guaranteed.
- *
- * @sa sink
- *
- * @tparam Event 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 Event>
- [[nodiscard]] auto sink(const id_type id = type_hash<Event>::value()) {
- return assure<Event>(id).bucket();
- }
- /**
- * @brief Triggers an immediate event of a given type.
- * @tparam Event Type of event to trigger.
- * @param event An instance of the given type of event.
- */
- template<typename Event>
- void trigger(Event &&event = {}) {
- trigger(type_hash<std::decay_t<Event>>::value(), std::forward<Event>(event));
- }
- /**
- * @brief Triggers an immediate event on a queue of a given type.
- * @tparam Event Type of event to trigger.
- * @param event An instance of the given type of event.
- * @param id Name used to map the event queue within the dispatcher.
- */
- template<typename Event>
- void trigger(const id_type id, Event &&event = {}) {
- assure<std::decay_t<Event>>(id).trigger(std::forward<Event>(event));
- }
- /**
- * @brief Enqueues an event of the given type.
- * @tparam Event 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 Event, typename... Args>
- void enqueue(Args &&...args) {
- enqueue_hint<Event>(type_hash<Event>::value(), std::forward<Args>(args)...);
- }
- /**
- * @brief Enqueues an event of the given type.
- * @tparam Event Type of event to enqueue.
- * @param event An instance of the given type of event.
- */
- template<typename Event>
- void enqueue(Event &&event) {
- enqueue_hint(type_hash<std::decay_t<Event>>::value(), std::forward<Event>(event));
- }
- /**
- * @brief Enqueues an event of the given type.
- * @tparam Event 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 Event, typename... Args>
- void enqueue_hint(const id_type id, Args &&...args) {
- assure<Event>(id).enqueue(std::forward<Args>(args)...);
- }
- /**
- * @brief Enqueues an event of the given type.
- * @tparam Event Type of event to enqueue.
- * @param id Name used to map the event queue within the dispatcher.
- * @param event An instance of the given type of event.
- */
- template<typename Event>
- void enqueue_hint(const id_type id, Event &&event) {
- assure<std::decay_t<Event>>(id).enqueue(std::forward<Event>(event));
- }
- /**
- * @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 Event Type of event to discard.
- * @param id Name used to map the event queue within the dispatcher.
- */
- template<typename Event>
- void clear(const id_type id = type_hash<Event>::value()) {
- assure<Event>(id).clear();
- }
- /*! @brief Discards all the events queued so far. */
- void clear() ENTT_NOEXCEPT {
- for(auto &&cpool: pools.first()) {
- cpool.second->clear();
- }
- }
- /**
- * @brief Delivers all the pending events of a given queue.
- * @tparam Event Type of event to send.
- * @param id Name used to map the event queue within the dispatcher.
- */
- template<typename Event>
- void update(const id_type id = type_hash<Event>::value()) {
- assure<Event>(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 <algorithm>
- #include <functional>
- #include <iterator>
- #include <list>
- #include <memory>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- // #include "../container/dense_map.hpp"
- // #include "../core/fwd.hpp"
- // #include "../core/type_info.hpp"
- // #include "../core/utility.hpp"
- // #include "fwd.hpp"
- namespace entt {
- /**
- * @brief General purpose event emitter.
- *
- * The emitter class template follows the CRTP idiom. To create a custom emitter
- * type, derived classes must inherit directly from the base class as:
- *
- * @code{.cpp}
- * struct my_emitter: emitter<my_emitter> {
- * // ...
- * }
- * @endcode
- *
- * Pools for the type of events are created internally on the fly. It's not
- * required to specify in advance the full list of accepted types.<br/>
- * Moreover, whenever an event is published, an emitter provides the listeners
- * with a reference to itself along with a reference to the event. Therefore
- * listeners have an handy way to work with it without incurring in the need of
- * capturing a reference to the emitter.
- *
- * @tparam Derived Actual type of emitter that extends the class template.
- */
- template<typename Derived>
- class emitter {
- struct basic_pool {
- virtual ~basic_pool() = default;
- virtual bool empty() const ENTT_NOEXCEPT = 0;
- virtual void clear() ENTT_NOEXCEPT = 0;
- };
- template<typename Event>
- struct pool_handler final: basic_pool {
- static_assert(std::is_same_v<Event, std::decay_t<Event>>, "Invalid event type");
- using listener_type = std::function<void(Event &, Derived &)>;
- using element_type = std::pair<bool, listener_type>;
- using container_type = std::list<element_type>;
- using connection_type = typename container_type::iterator;
- [[nodiscard]] bool empty() const ENTT_NOEXCEPT override {
- auto pred = [](auto &&element) { return element.first; };
- return std::all_of(once_list.cbegin(), once_list.cend(), pred)
- && std::all_of(on_list.cbegin(), on_list.cend(), pred);
- }
- void clear() ENTT_NOEXCEPT override {
- if(publishing) {
- for(auto &&element: once_list) {
- element.first = true;
- }
- for(auto &&element: on_list) {
- element.first = true;
- }
- } else {
- once_list.clear();
- on_list.clear();
- }
- }
- connection_type once(listener_type listener) {
- return once_list.emplace(once_list.cend(), false, std::move(listener));
- }
- connection_type on(listener_type listener) {
- return on_list.emplace(on_list.cend(), false, std::move(listener));
- }
- void erase(connection_type conn) {
- conn->first = true;
- if(!publishing) {
- auto pred = [](auto &&element) { return element.first; };
- once_list.remove_if(pred);
- on_list.remove_if(pred);
- }
- }
- void publish(Event &event, Derived &ref) {
- container_type swap_list;
- once_list.swap(swap_list);
- publishing = true;
- for(auto &&element: on_list) {
- element.first ? void() : element.second(event, ref);
- }
- for(auto &&element: swap_list) {
- element.first ? void() : element.second(event, ref);
- }
- publishing = false;
- on_list.remove_if([](auto &&element) { return element.first; });
- }
- private:
- bool publishing{false};
- container_type once_list{};
- container_type on_list{};
- };
- template<typename Event>
- [[nodiscard]] pool_handler<Event> *assure() {
- if(auto &&ptr = pools[type_hash<Event>::value()]; !ptr) {
- auto *cpool = new pool_handler<Event>{};
- ptr.reset(cpool);
- return cpool;
- } else {
- return static_cast<pool_handler<Event> *>(ptr.get());
- }
- }
- template<typename Event>
- [[nodiscard]] const pool_handler<Event> *assure() const {
- const auto it = pools.find(type_hash<Event>::value());
- return (it == pools.cend()) ? nullptr : static_cast<const pool_handler<Event> *>(it->second.get());
- }
- public:
- /** @brief Type of listeners accepted for the given event. */
- template<typename Event>
- using listener = typename pool_handler<Event>::listener_type;
- /**
- * @brief Generic connection type for events.
- *
- * Type of the connection object returned by the event emitter whenever a
- * listener for the given type is registered.<br/>
- * It can be used to break connections still in use.
- *
- * @tparam Event Type of event for which the connection is created.
- */
- template<typename Event>
- struct connection: private pool_handler<Event>::connection_type {
- /** @brief Event emitters are friend classes of connections. */
- friend class emitter;
- /*! @brief Default constructor. */
- connection() ENTT_NOEXCEPT = default;
- /**
- * @brief Creates a connection that wraps its underlying instance.
- * @param conn A connection object to wrap.
- */
- connection(typename pool_handler<Event>::connection_type conn)
- : pool_handler<Event>::connection_type{std::move(conn)} {}
- };
- /*! @brief Default constructor. */
- emitter() = default;
- /*! @brief Default destructor. */
- virtual ~emitter() ENTT_NOEXCEPT {
- static_assert(std::is_base_of_v<emitter<Derived>, Derived>, "Incorrect use of the class template");
- }
- /*! @brief Default move constructor. */
- emitter(emitter &&) = default;
- /*! @brief Default move assignment operator. @return This emitter. */
- emitter &operator=(emitter &&) = default;
- /**
- * @brief Emits the given event.
- *
- * All the listeners registered for the specific event type are invoked with
- * the given event. The event type must either have a proper constructor for
- * the arguments provided or be an aggregate type.
- *
- * @tparam Event Type of event to publish.
- * @tparam Args Types of arguments to use to construct the event.
- * @param args Parameters to use to initialize the event.
- */
- template<typename Event, typename... Args>
- void publish(Args &&...args) {
- Event instance{std::forward<Args>(args)...};
- assure<Event>()->publish(instance, *static_cast<Derived *>(this));
- }
- /**
- * @brief Registers a long-lived listener with the event emitter.
- *
- * This method can be used to register a listener designed to be invoked
- * more than once for the given event type.<br/>
- * The connection returned by the method can be freely discarded. It's meant
- * to be used later to disconnect the listener if required.
- *
- * The listener is as a callable object that can be moved and the type of
- * which is _compatible_ with `void(Event &, Derived &)`.
- *
- * @note
- * Whenever an event is emitted, the emitter provides the listener with a
- * reference to the derived class. Listeners don't have to capture those
- * instances for later uses.
- *
- * @tparam Event Type of event to which to connect the listener.
- * @param instance The listener to register.
- * @return Connection object that can be used to disconnect the listener.
- */
- template<typename Event>
- connection<Event> on(listener<Event> instance) {
- return assure<Event>()->on(std::move(instance));
- }
- /**
- * @brief Registers a short-lived listener with the event emitter.
- *
- * This method can be used to register a listener designed to be invoked
- * only once for the given event type.<br/>
- * The connection returned by the method can be freely discarded. It's meant
- * to be used later to disconnect the listener if required.
- *
- * The listener is as a callable object that can be moved and the type of
- * which is _compatible_ with `void(Event &, Derived &)`.
- *
- * @note
- * Whenever an event is emitted, the emitter provides the listener with a
- * reference to the derived class. Listeners don't have to capture those
- * instances for later uses.
- *
- * @tparam Event Type of event to which to connect the listener.
- * @param instance The listener to register.
- * @return Connection object that can be used to disconnect the listener.
- */
- template<typename Event>
- connection<Event> once(listener<Event> instance) {
- return assure<Event>()->once(std::move(instance));
- }
- /**
- * @brief Disconnects a listener from the event emitter.
- *
- * Do not use twice the same connection to disconnect a listener, it results
- * in undefined behavior. Once used, discard the connection object.
- *
- * @tparam Event Type of event of the connection.
- * @param conn A valid connection.
- */
- template<typename Event>
- void erase(connection<Event> conn) {
- assure<Event>()->erase(std::move(conn));
- }
- /**
- * @brief Disconnects all the listeners for the given event type.
- *
- * All the connections previously returned for the given event are
- * invalidated. Using them results in undefined behavior.
- *
- * @tparam Event Type of event to reset.
- */
- template<typename Event>
- void clear() {
- assure<Event>()->clear();
- }
- /**
- * @brief Disconnects all the listeners.
- *
- * All the connections previously returned are invalidated. Using them
- * results in undefined behavior.
- */
- void clear() ENTT_NOEXCEPT {
- for(auto &&cpool: pools) {
- cpool.second->clear();
- }
- }
- /**
- * @brief Checks if there are listeners registered for the specific event.
- * @tparam Event Type of event to test.
- * @return True if there are no listeners registered, false otherwise.
- */
- template<typename Event>
- [[nodiscard]] bool empty() const {
- const auto *cpool = assure<Event>();
- return !cpool || cpool->empty();
- }
- /**
- * @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 ENTT_NOEXCEPT {
- return std::all_of(pools.cbegin(), pools.cend(), [](auto &&cpool) {
- return cpool.second->empty();
- });
- }
- private:
- dense_map<id_type, std::unique_ptr<basic_pool>, identity> pools{};
- };
- } // namespace entt
- #endif
- // #include "signal/sigh.hpp"
- #ifndef ENTT_SIGNAL_SIGH_HPP
- #define ENTT_SIGNAL_SIGH_HPP
- #include <algorithm>
- #include <functional>
- #include <type_traits>
- #include <utility>
- #include <vector>
- // #include "../config/config.h"
- // #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> {
- /*! @brief A sink is allowed to modify a signal. */
- friend class sink<sigh<Ret(Args...), Allocator>>;
- using alloc_traits = std::allocator_traits<Allocator>;
- static_assert(std::is_same_v<typename alloc_traits::value_type, Ret (*)(Args...)>, "Invalid value type");
- using container_type = std::vector<delegate<Ret(Args...)>, typename alloc_traits::template rebind_alloc<delegate<Ret(Args...)>>>;
- 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()
- : sigh{allocator_type{}} {}
- /**
- * @brief Constructs a signal handler with a given allocator.
- * @param allocator The allocator to use.
- */
- explicit sigh(const allocator_type &allocator)
- : 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) ENTT_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) ENTT_NOEXCEPT
- : calls{std::move(other.calls), allocator} {}
- /**
- * @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) ENTT_NOEXCEPT {
- calls = std::move(other.calls);
- 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) {
- using std::swap;
- swap(calls, other.calls);
- }
- /**
- * @brief Returns the associated allocator.
- * @return The associated allocator.
- */
- [[nodiscard]] constexpr allocator_type get_allocator() const ENTT_NOEXCEPT {
- return calls.get_allocator();
- }
- /**
- * @brief Instance type when it comes to connecting member functions.
- * @tparam Class Type of class to which the member function belongs.
- */
- template<typename Class>
- using instance_type = Class *;
- /**
- * @brief Number of listeners connected to the signal.
- * @return Number of listeners currently connected.
- */
- [[nodiscard]] size_type size() const ENTT_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 ENTT_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 &&call: std::as_const(calls)) {
- call(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 &&call: calls) {
- if constexpr(std::is_void_v<Ret>) {
- if constexpr(std::is_invocable_r_v<bool, Func>) {
- call(args...);
- if(func()) { break; }
- } else {
- call(args...);
- func();
- }
- } else {
- if constexpr(std::is_invocable_r_v<bool, Func, Ret>) {
- if(func(call(args...))) { break; }
- } else {
- func(call(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 {
- /*! @brief A sink is allowed to create connection objects. */
- template<typename>
- friend class sink;
- connection(delegate<void(void *)> fn, void *ref)
- : disconnect{fn}, signal{ref} {}
- public:
- /*! @brief Default constructor. */
- connection() = default;
- /**
- * @brief Checks whether a connection is properly initialized.
- * @return True if the connection is properly initialized, false otherwise.
- */
- [[nodiscard]] explicit operator bool() const ENTT_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) ENTT_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) ENTT_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 = std::move(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 ENTT_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 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>();
- }
- public:
- /**
- * @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) ENTT_NOEXCEPT
- : offset{},
- 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 ENTT_NOEXCEPT {
- return signal->calls.empty();
- }
- /**
- * @brief Returns a sink that connects before a given free function or an
- * unbound member.
- * @tparam Function A valid free function pointer.
- * @return A properly initialized sink object.
- */
- template<auto Function>
- [[nodiscard]] sink before() {
- delegate<Ret(Args...)> call{};
- call.template connect<Function>();
- const auto &calls = signal->calls;
- const auto it = std::find(calls.cbegin(), calls.cend(), std::move(call));
- sink other{*this};
- other.offset = calls.cend() - it;
- return other;
- }
- /**
- * @brief Returns a sink that connects before a free function with payload
- * or a bound member.
- * @tparam Candidate Member or free function to look for.
- * @tparam Type Type of class or type of payload.
- * @param value_or_instance A valid object that fits the purpose.
- * @return A properly initialized sink object.
- */
- template<auto Candidate, typename Type>
- [[nodiscard]] sink before(Type &&value_or_instance) {
- delegate<Ret(Args...)> call{};
- call.template connect<Candidate>(value_or_instance);
- const auto &calls = signal->calls;
- const auto it = std::find(calls.cbegin(), calls.cend(), std::move(call));
- sink other{*this};
- other.offset = calls.cend() - it;
- return other;
- }
- /**
- * @brief Returns a sink that connects before a given instance or specific
- * payload.
- * @tparam Type Type of class or type of payload.
- * @param value_or_instance A valid object that fits the purpose.
- * @return A properly initialized sink object.
- */
- template<typename Type>
- [[nodiscard]] sink before(Type &value_or_instance) {
- return before(&value_or_instance);
- }
- /**
- * @brief Returns a sink that connects before a given instance or specific
- * payload.
- * @tparam Type Type of class or type of payload.
- * @param value_or_instance A valid pointer that fits the purpose.
- * @return A properly initialized sink object.
- */
- template<typename Type>
- [[nodiscard]] sink before(Type *value_or_instance) {
- sink other{*this};
- if(value_or_instance) {
- const auto &calls = signal->calls;
- const auto it = std::find_if(calls.cbegin(), calls.cend(), [value_or_instance](const auto &delegate) {
- return delegate.data() == value_or_instance;
- });
- other.offset = calls.cend() - it;
- }
- return other;
- }
- /**
- * @brief Returns a sink that connects before anything else.
- * @return A properly initialized sink object.
- */
- [[nodiscard]] sink before() {
- sink other{*this};
- other.offset = signal->calls.size();
- return other;
- }
- /**
- * @brief Connects a free function or an unbound member to a signal.
- *
- * The signal handler performs checks to avoid multiple connections for the
- * same function.
- *
- * @tparam Candidate Function or member to connect to the signal.
- * @return A properly initialized connection object.
- */
- template<auto Candidate>
- connection connect() {
- disconnect<Candidate>();
- delegate<Ret(Args...)> call{};
- call.template connect<Candidate>();
- signal->calls.insert(signal->calls.end() - offset, std::move(call));
- delegate<void(void *)> conn{};
- conn.template connect<&release<Candidate>>();
- return {std::move(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. On the other side, the signal handler performs
- * checks to avoid multiple connections for the same function.<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 object 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<Ret(Args...)> call{};
- call.template connect<Candidate>(value_or_instance);
- signal->calls.insert(signal->calls.end() - offset, std::move(call));
- delegate<void(void *)> conn{};
- conn.template connect<&release<Candidate, Type>>(value_or_instance);
- return {std::move(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() {
- auto &calls = signal->calls;
- delegate<Ret(Args...)> call{};
- call.template connect<Candidate>();
- calls.erase(std::remove(calls.begin(), calls.end(), std::move(call)), calls.end());
- }
- /**
- * @brief Disconnects a free function with payload or a bound member from a
- * signal.
- * @tparam Candidate Function or member to disconnect from the signal.
- * @tparam Type Type of class or type of payload.
- * @param value_or_instance A valid object that fits the purpose.
- */
- template<auto Candidate, typename Type>
- void disconnect(Type &&value_or_instance) {
- auto &calls = signal->calls;
- delegate<Ret(Args...)> call{};
- call.template connect<Candidate>(value_or_instance);
- calls.erase(std::remove(calls.begin(), calls.end(), std::move(call)), calls.end());
- }
- /**
- * @brief Disconnects free functions with payload or bound members from a
- * signal.
- * @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 Disconnects free functions with payload or bound members from a
- * signal.
- * @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) {
- if(value_or_instance) {
- auto &calls = signal->calls;
- auto predicate = [value_or_instance](const auto &delegate) { return delegate.data() == value_or_instance; };
- calls.erase(std::remove_if(calls.begin(), calls.end(), std::move(predicate)), calls.end());
- }
- }
- /*! @brief Disconnects all the listeners from a signal. */
- void disconnect() {
- signal->calls.clear();
- }
- private:
- difference_type offset;
- 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
|