| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715771677177718771977207721772277237724772577267727772877297730773177327733773477357736773777387739774077417742774377447745774677477748774977507751775277537754775577567757775877597760776177627763776477657766776777687769777077717772777377747775777677777778777977807781778277837784778577867787778877897790779177927793779477957796779777987799780078017802780378047805780678077808780978107811781278137814781578167817781878197820782178227823782478257826782778287829783078317832783378347835783678377838783978407841784278437844784578467847784878497850785178527853785478557856785778587859786078617862786378647865786678677868786978707871787278737874787578767877787878797880788178827883788478857886788778887889789078917892789378947895789678977898789979007901790279037904790579067907790879097910791179127913791479157916791779187919792079217922792379247925792679277928792979307931793279337934793579367937793879397940794179427943794479457946794779487949795079517952795379547955795679577958795979607961796279637964796579667967796879697970797179727973797479757976797779787979798079817982798379847985798679877988798979907991799279937994799579967997799879998000800180028003800480058006800780088009801080118012801380148015801680178018801980208021802280238024802580268027802880298030803180328033803480358036803780388039804080418042804380448045804680478048804980508051805280538054805580568057805880598060806180628063806480658066806780688069807080718072807380748075807680778078807980808081808280838084808580868087808880898090809180928093809480958096809780988099810081018102810381048105810681078108810981108111811281138114811581168117811881198120812181228123812481258126812781288129813081318132813381348135813681378138813981408141814281438144814581468147814881498150815181528153815481558156815781588159816081618162816381648165816681678168816981708171817281738174817581768177817881798180818181828183818481858186818781888189819081918192819381948195819681978198819982008201820282038204820582068207820882098210821182128213821482158216821782188219822082218222822382248225822682278228822982308231823282338234823582368237823882398240824182428243824482458246824782488249825082518252825382548255825682578258825982608261826282638264826582668267826882698270827182728273827482758276827782788279828082818282828382848285828682878288828982908291829282938294829582968297829882998300830183028303830483058306830783088309831083118312831383148315831683178318831983208321832283238324832583268327832883298330833183328333833483358336833783388339834083418342834383448345834683478348834983508351835283538354835583568357835883598360836183628363836483658366836783688369837083718372837383748375837683778378837983808381838283838384838583868387838883898390839183928393839483958396839783988399840084018402840384048405840684078408840984108411841284138414841584168417841884198420842184228423842484258426842784288429843084318432843384348435843684378438843984408441844284438444844584468447844884498450845184528453845484558456845784588459846084618462846384648465846684678468846984708471847284738474847584768477847884798480848184828483848484858486848784888489849084918492849384948495849684978498849985008501850285038504850585068507850885098510851185128513851485158516851785188519852085218522852385248525852685278528852985308531853285338534853585368537853885398540854185428543854485458546854785488549855085518552855385548555855685578558855985608561856285638564856585668567856885698570857185728573857485758576857785788579858085818582858385848585858685878588858985908591859285938594859585968597859885998600860186028603860486058606860786088609861086118612861386148615861686178618861986208621862286238624862586268627862886298630863186328633863486358636863786388639864086418642864386448645864686478648864986508651865286538654865586568657865886598660866186628663866486658666866786688669867086718672867386748675867686778678867986808681868286838684868586868687868886898690869186928693869486958696869786988699870087018702870387048705870687078708870987108711871287138714871587168717871887198720872187228723872487258726872787288729873087318732873387348735873687378738873987408741874287438744874587468747874887498750875187528753875487558756875787588759876087618762876387648765876687678768876987708771877287738774877587768777877887798780878187828783878487858786878787888789879087918792879387948795879687978798879988008801880288038804880588068807880888098810881188128813881488158816881788188819882088218822882388248825882688278828882988308831883288338834883588368837883888398840884188428843884488458846884788488849885088518852885388548855885688578858885988608861886288638864886588668867886888698870887188728873887488758876887788788879888088818882888388848885888688878888888988908891889288938894889588968897889888998900890189028903890489058906890789088909891089118912891389148915891689178918891989208921892289238924892589268927892889298930893189328933893489358936893789388939894089418942894389448945894689478948894989508951895289538954895589568957895889598960896189628963896489658966896789688969897089718972897389748975897689778978897989808981898289838984898589868987898889898990899189928993899489958996899789988999900090019002900390049005900690079008900990109011901290139014901590169017901890199020902190229023902490259026902790289029903090319032903390349035903690379038903990409041904290439044904590469047904890499050905190529053905490559056905790589059906090619062906390649065906690679068906990709071907290739074907590769077907890799080908190829083908490859086908790889089909090919092909390949095909690979098909991009101910291039104910591069107910891099110911191129113911491159116911791189119912091219122912391249125912691279128912991309131913291339134913591369137913891399140914191429143914491459146914791489149915091519152915391549155915691579158915991609161916291639164916591669167916891699170917191729173917491759176917791789179918091819182918391849185918691879188918991909191919291939194919591969197919891999200920192029203920492059206920792089209921092119212921392149215921692179218921992209221922292239224922592269227922892299230923192329233923492359236923792389239924092419242924392449245924692479248924992509251925292539254925592569257925892599260926192629263926492659266926792689269927092719272927392749275927692779278927992809281928292839284928592869287928892899290929192929293929492959296929792989299930093019302930393049305930693079308930993109311931293139314931593169317931893199320932193229323932493259326932793289329933093319332933393349335933693379338933993409341934293439344934593469347934893499350935193529353935493559356935793589359936093619362936393649365936693679368936993709371937293739374937593769377937893799380938193829383938493859386938793889389939093919392939393949395939693979398939994009401940294039404940594069407940894099410941194129413941494159416941794189419942094219422942394249425942694279428942994309431943294339434943594369437943894399440944194429443944494459446944794489449945094519452945394549455945694579458945994609461946294639464946594669467946894699470947194729473947494759476947794789479948094819482948394849485948694879488948994909491949294939494949594969497949894999500950195029503950495059506950795089509951095119512951395149515951695179518951995209521952295239524952595269527952895299530953195329533953495359536953795389539954095419542954395449545954695479548954995509551955295539554955595569557955895599560956195629563956495659566956795689569957095719572957395749575957695779578957995809581958295839584958595869587958895899590959195929593959495959596959795989599960096019602960396049605960696079608960996109611961296139614961596169617961896199620962196229623962496259626962796289629963096319632963396349635963696379638963996409641964296439644964596469647964896499650965196529653965496559656965796589659966096619662966396649665966696679668966996709671967296739674967596769677967896799680968196829683968496859686968796889689969096919692969396949695969696979698969997009701970297039704970597069707970897099710971197129713971497159716971797189719972097219722972397249725972697279728972997309731973297339734973597369737973897399740974197429743974497459746974797489749975097519752975397549755975697579758975997609761976297639764976597669767976897699770977197729773977497759776977797789779978097819782978397849785978697879788978997909791979297939794979597969797979897999800980198029803980498059806980798089809981098119812981398149815981698179818981998209821982298239824982598269827982898299830983198329833983498359836983798389839984098419842984398449845984698479848984998509851985298539854985598569857985898599860986198629863986498659866986798689869987098719872987398749875987698779878987998809881988298839884988598869887988898899890989198929893989498959896989798989899990099019902990399049905990699079908990999109911991299139914991599169917991899199920992199229923992499259926992799289929993099319932993399349935993699379938993999409941994299439944994599469947994899499950995199529953995499559956995799589959996099619962996399649965996699679968996999709971997299739974997599769977997899799980998199829983998499859986998799889989999099919992999399949995999699979998999910000100011000210003100041000510006100071000810009100101001110012100131001410015100161001710018100191002010021100221002310024100251002610027100281002910030100311003210033100341003510036100371003810039100401004110042100431004410045100461004710048100491005010051100521005310054100551005610057100581005910060100611006210063100641006510066100671006810069100701007110072100731007410075100761007710078100791008010081100821008310084100851008610087100881008910090100911009210093100941009510096100971009810099101001010110102101031010410105101061010710108101091011010111101121011310114101151011610117101181011910120101211012210123101241012510126101271012810129101301013110132101331013410135101361013710138101391014010141101421014310144101451014610147101481014910150101511015210153101541015510156101571015810159101601016110162101631016410165101661016710168101691017010171101721017310174101751017610177101781017910180101811018210183101841018510186101871018810189101901019110192101931019410195101961019710198101991020010201102021020310204102051020610207102081020910210102111021210213102141021510216102171021810219102201022110222102231022410225102261022710228102291023010231102321023310234102351023610237102381023910240102411024210243102441024510246102471024810249102501025110252102531025410255102561025710258102591026010261102621026310264102651026610267102681026910270102711027210273102741027510276102771027810279102801028110282102831028410285102861028710288102891029010291102921029310294102951029610297102981029910300103011030210303103041030510306103071030810309103101031110312103131031410315103161031710318103191032010321103221032310324103251032610327103281032910330103311033210333103341033510336103371033810339103401034110342103431034410345103461034710348103491035010351103521035310354103551035610357103581035910360103611036210363103641036510366103671036810369103701037110372103731037410375103761037710378103791038010381103821038310384103851038610387103881038910390103911039210393103941039510396103971039810399104001040110402104031040410405104061040710408104091041010411104121041310414104151041610417104181041910420104211042210423104241042510426104271042810429104301043110432104331043410435104361043710438104391044010441104421044310444104451044610447104481044910450104511045210453104541045510456104571045810459104601046110462104631046410465104661046710468104691047010471104721047310474104751047610477104781047910480104811048210483104841048510486104871048810489104901049110492104931049410495104961049710498104991050010501105021050310504105051050610507105081050910510105111051210513105141051510516105171051810519105201052110522105231052410525105261052710528105291053010531105321053310534105351053610537105381053910540105411054210543105441054510546105471054810549105501055110552105531055410555105561055710558105591056010561105621056310564105651056610567105681056910570105711057210573105741057510576105771057810579105801058110582105831058410585105861058710588105891059010591105921059310594105951059610597105981059910600106011060210603106041060510606106071060810609106101061110612106131061410615106161061710618106191062010621106221062310624106251062610627106281062910630106311063210633106341063510636106371063810639106401064110642106431064410645106461064710648106491065010651106521065310654106551065610657106581065910660106611066210663106641066510666106671066810669106701067110672106731067410675106761067710678106791068010681106821068310684106851068610687106881068910690106911069210693106941069510696106971069810699107001070110702107031070410705107061070710708107091071010711107121071310714107151071610717107181071910720107211072210723107241072510726107271072810729107301073110732107331073410735107361073710738107391074010741107421074310744107451074610747107481074910750107511075210753107541075510756107571075810759107601076110762107631076410765107661076710768107691077010771107721077310774107751077610777107781077910780107811078210783107841078510786107871078810789107901079110792107931079410795107961079710798107991080010801108021080310804108051080610807108081080910810108111081210813108141081510816108171081810819108201082110822108231082410825108261082710828108291083010831108321083310834108351083610837108381083910840108411084210843108441084510846108471084810849108501085110852108531085410855108561085710858108591086010861108621086310864108651086610867108681086910870108711087210873108741087510876108771087810879108801088110882108831088410885108861088710888108891089010891108921089310894108951089610897108981089910900109011090210903109041090510906109071090810909109101091110912109131091410915109161091710918109191092010921109221092310924109251092610927109281092910930109311093210933109341093510936109371093810939109401094110942109431094410945109461094710948109491095010951109521095310954109551095610957109581095910960109611096210963109641096510966109671096810969109701097110972109731097410975109761097710978109791098010981109821098310984109851098610987109881098910990109911099210993109941099510996109971099810999110001100111002110031100411005110061100711008110091101011011110121101311014110151101611017110181101911020110211102211023110241102511026110271102811029110301103111032110331103411035110361103711038110391104011041110421104311044110451104611047110481104911050110511105211053110541105511056110571105811059110601106111062110631106411065110661106711068110691107011071110721107311074110751107611077110781107911080110811108211083110841108511086110871108811089110901109111092110931109411095110961109711098110991110011101111021110311104111051110611107111081110911110111111111211113111141111511116111171111811119111201112111122111231112411125111261112711128111291113011131111321113311134111351113611137111381113911140111411114211143111441114511146111471114811149111501115111152111531115411155111561115711158111591116011161111621116311164111651116611167111681116911170111711117211173111741117511176111771117811179111801118111182111831118411185111861118711188111891119011191111921119311194111951119611197111981119911200112011120211203112041120511206112071120811209112101121111212112131121411215112161121711218112191122011221112221122311224112251122611227112281122911230112311123211233112341123511236112371123811239112401124111242112431124411245112461124711248112491125011251112521125311254112551125611257112581125911260112611126211263112641126511266112671126811269112701127111272112731127411275112761127711278112791128011281112821128311284112851128611287112881128911290112911129211293112941129511296112971129811299113001130111302113031130411305113061130711308113091131011311113121131311314113151131611317113181131911320113211132211323113241132511326113271132811329113301133111332113331133411335113361133711338113391134011341113421134311344113451134611347113481134911350113511135211353113541135511356113571135811359113601136111362113631136411365113661136711368113691137011371113721137311374113751137611377113781137911380113811138211383113841138511386113871138811389113901139111392113931139411395113961139711398113991140011401114021140311404114051140611407114081140911410114111141211413114141141511416114171141811419114201142111422114231142411425114261142711428114291143011431114321143311434114351143611437114381143911440114411144211443114441144511446114471144811449114501145111452114531145411455114561145711458114591146011461114621146311464114651146611467114681146911470114711147211473114741147511476114771147811479114801148111482114831148411485114861148711488114891149011491114921149311494114951149611497114981149911500115011150211503115041150511506115071150811509115101151111512115131151411515115161151711518115191152011521115221152311524115251152611527115281152911530115311153211533115341153511536115371153811539115401154111542115431154411545115461154711548115491155011551115521155311554115551155611557115581155911560115611156211563115641156511566115671156811569115701157111572115731157411575115761157711578115791158011581115821158311584115851158611587115881158911590115911159211593115941159511596115971159811599116001160111602116031160411605116061160711608116091161011611116121161311614116151161611617116181161911620116211162211623116241162511626116271162811629116301163111632116331163411635116361163711638116391164011641116421164311644116451164611647116481164911650116511165211653116541165511656116571165811659116601166111662116631166411665116661166711668116691167011671116721167311674116751167611677116781167911680116811168211683116841168511686116871168811689116901169111692116931169411695116961169711698116991170011701117021170311704117051170611707117081170911710117111171211713117141171511716117171171811719117201172111722117231172411725117261172711728117291173011731117321173311734117351173611737117381173911740117411174211743117441174511746117471174811749117501175111752117531175411755117561175711758117591176011761117621176311764117651176611767117681176911770117711177211773117741177511776117771177811779117801178111782117831178411785117861178711788117891179011791117921179311794117951179611797117981179911800118011180211803118041180511806118071180811809118101181111812118131181411815118161181711818118191182011821118221182311824118251182611827118281182911830118311183211833118341183511836118371183811839118401184111842118431184411845118461184711848118491185011851118521185311854118551185611857118581185911860118611186211863118641186511866118671186811869118701187111872118731187411875118761187711878118791188011881118821188311884118851188611887118881188911890118911189211893118941189511896118971189811899119001190111902119031190411905119061190711908119091191011911119121191311914119151191611917119181191911920119211192211923119241192511926119271192811929119301193111932119331193411935119361193711938119391194011941119421194311944119451194611947119481194911950119511195211953119541195511956119571195811959119601196111962119631196411965119661196711968119691197011971119721197311974119751197611977119781197911980119811198211983119841198511986119871198811989119901199111992119931199411995119961199711998119991200012001120021200312004120051200612007120081200912010120111201212013120141201512016120171201812019120201202112022120231202412025120261202712028120291203012031120321203312034120351203612037120381203912040120411204212043120441204512046120471204812049120501205112052120531205412055120561205712058120591206012061120621206312064120651206612067120681206912070120711207212073120741207512076120771207812079120801208112082120831208412085120861208712088120891209012091120921209312094120951209612097120981209912100121011210212103121041210512106121071210812109121101211112112121131211412115121161211712118121191212012121121221212312124121251212612127121281212912130121311213212133121341213512136121371213812139121401214112142121431214412145121461214712148121491215012151121521215312154121551215612157121581215912160121611216212163121641216512166121671216812169121701217112172121731217412175121761217712178121791218012181121821218312184121851218612187121881218912190121911219212193121941219512196121971219812199122001220112202122031220412205122061220712208122091221012211122121221312214122151221612217122181221912220122211222212223122241222512226122271222812229122301223112232122331223412235122361223712238122391224012241122421224312244122451224612247122481224912250122511225212253122541225512256122571225812259122601226112262122631226412265122661226712268122691227012271122721227312274122751227612277122781227912280122811228212283122841228512286122871228812289122901229112292122931229412295122961229712298122991230012301123021230312304123051230612307123081230912310123111231212313123141231512316123171231812319123201232112322123231232412325123261232712328123291233012331123321233312334123351233612337123381233912340123411234212343123441234512346123471234812349123501235112352123531235412355123561235712358123591236012361123621236312364123651236612367123681236912370123711237212373123741237512376123771237812379123801238112382123831238412385123861238712388123891239012391123921239312394123951239612397123981239912400124011240212403124041240512406124071240812409124101241112412124131241412415124161241712418124191242012421124221242312424124251242612427124281242912430124311243212433124341243512436124371243812439124401244112442124431244412445124461244712448124491245012451124521245312454124551245612457124581245912460124611246212463124641246512466124671246812469124701247112472124731247412475124761247712478124791248012481124821248312484124851248612487124881248912490124911249212493124941249512496124971249812499125001250112502125031250412505125061250712508125091251012511125121251312514125151251612517125181251912520125211252212523125241252512526125271252812529125301253112532125331253412535125361253712538125391254012541125421254312544125451254612547125481254912550125511255212553125541255512556125571255812559125601256112562125631256412565125661256712568125691257012571125721257312574125751257612577125781257912580125811258212583125841258512586125871258812589125901259112592125931259412595125961259712598125991260012601126021260312604126051260612607126081260912610126111261212613126141261512616126171261812619126201262112622126231262412625126261262712628126291263012631126321263312634126351263612637126381263912640126411264212643126441264512646126471264812649126501265112652126531265412655126561265712658126591266012661126621266312664126651266612667126681266912670126711267212673126741267512676126771267812679126801268112682126831268412685126861268712688126891269012691126921269312694126951269612697126981269912700127011270212703127041270512706127071270812709127101271112712127131271412715127161271712718127191272012721127221272312724127251272612727127281272912730127311273212733127341273512736127371273812739127401274112742127431274412745127461274712748127491275012751127521275312754127551275612757127581275912760127611276212763127641276512766127671276812769127701277112772127731277412775127761277712778127791278012781127821278312784127851278612787127881278912790127911279212793127941279512796127971279812799128001280112802128031280412805128061280712808128091281012811128121281312814128151281612817128181281912820128211282212823128241282512826128271282812829128301283112832128331283412835128361283712838128391284012841128421284312844128451284612847128481284912850128511285212853128541285512856128571285812859128601286112862128631286412865128661286712868128691287012871128721287312874128751287612877128781287912880128811288212883128841288512886128871288812889128901289112892128931289412895128961289712898128991290012901129021290312904129051290612907129081290912910129111291212913129141291512916129171291812919129201292112922129231292412925129261292712928129291293012931129321293312934129351293612937129381293912940129411294212943129441294512946129471294812949129501295112952129531295412955129561295712958129591296012961129621296312964129651296612967129681296912970129711297212973129741297512976129771297812979129801298112982129831298412985129861298712988129891299012991129921299312994129951299612997129981299913000130011300213003130041300513006130071300813009130101301113012130131301413015130161301713018130191302013021130221302313024130251302613027130281302913030130311303213033130341303513036130371303813039130401304113042130431304413045130461304713048130491305013051130521305313054130551305613057130581305913060130611306213063130641306513066130671306813069130701307113072130731307413075130761307713078130791308013081130821308313084130851308613087130881308913090130911309213093130941309513096130971309813099131001310113102131031310413105131061310713108131091311013111131121311313114131151311613117131181311913120131211312213123131241312513126131271312813129131301313113132131331313413135131361313713138131391314013141131421314313144131451314613147131481314913150131511315213153131541315513156131571315813159131601316113162131631316413165131661316713168131691317013171131721317313174131751317613177131781317913180131811318213183131841318513186131871318813189131901319113192131931319413195131961319713198131991320013201132021320313204132051320613207132081320913210132111321213213132141321513216132171321813219132201322113222132231322413225132261322713228132291323013231132321323313234132351323613237132381323913240132411324213243132441324513246132471324813249132501325113252132531325413255132561325713258132591326013261132621326313264132651326613267132681326913270132711327213273132741327513276132771327813279132801328113282132831328413285132861328713288132891329013291132921329313294132951329613297132981329913300133011330213303133041330513306133071330813309133101331113312133131331413315133161331713318133191332013321133221332313324133251332613327133281332913330133311333213333133341333513336133371333813339133401334113342133431334413345133461334713348133491335013351133521335313354133551335613357133581335913360133611336213363133641336513366133671336813369133701337113372133731337413375133761337713378133791338013381133821338313384133851338613387133881338913390133911339213393133941339513396133971339813399134001340113402134031340413405134061340713408134091341013411134121341313414134151341613417134181341913420134211342213423134241342513426134271342813429134301343113432134331343413435134361343713438134391344013441134421344313444134451344613447134481344913450134511345213453134541345513456134571345813459134601346113462134631346413465134661346713468134691347013471134721347313474134751347613477134781347913480134811348213483134841348513486134871348813489134901349113492134931349413495134961349713498134991350013501135021350313504135051350613507135081350913510135111351213513135141351513516135171351813519135201352113522135231352413525135261352713528135291353013531135321353313534135351353613537135381353913540135411354213543135441354513546135471354813549135501355113552135531355413555135561355713558135591356013561135621356313564135651356613567135681356913570135711357213573135741357513576135771357813579135801358113582135831358413585135861358713588135891359013591135921359313594135951359613597135981359913600136011360213603136041360513606136071360813609136101361113612136131361413615136161361713618136191362013621136221362313624136251362613627136281362913630136311363213633136341363513636136371363813639136401364113642136431364413645136461364713648136491365013651136521365313654136551365613657136581365913660136611366213663136641366513666136671366813669136701367113672136731367413675136761367713678136791368013681136821368313684136851368613687136881368913690136911369213693136941369513696136971369813699137001370113702137031370413705137061370713708137091371013711137121371313714137151371613717137181371913720137211372213723137241372513726137271372813729137301373113732137331373413735137361373713738137391374013741137421374313744137451374613747137481374913750137511375213753137541375513756137571375813759137601376113762137631376413765137661376713768137691377013771137721377313774137751377613777137781377913780137811378213783137841378513786137871378813789137901379113792137931379413795137961379713798137991380013801138021380313804138051380613807138081380913810138111381213813138141381513816138171381813819138201382113822138231382413825138261382713828138291383013831138321383313834138351383613837138381383913840138411384213843138441384513846138471384813849138501385113852138531385413855138561385713858138591386013861138621386313864138651386613867138681386913870138711387213873138741387513876138771387813879138801388113882138831388413885138861388713888138891389013891138921389313894138951389613897138981389913900139011390213903139041390513906139071390813909139101391113912139131391413915139161391713918139191392013921139221392313924139251392613927139281392913930139311393213933139341393513936139371393813939139401394113942139431394413945139461394713948139491395013951139521395313954139551395613957139581395913960139611396213963139641396513966139671396813969139701397113972139731397413975139761397713978139791398013981139821398313984139851398613987139881398913990139911399213993139941399513996139971399813999140001400114002140031400414005140061400714008140091401014011140121401314014140151401614017140181401914020140211402214023140241402514026140271402814029140301403114032140331403414035140361403714038140391404014041140421404314044140451404614047140481404914050140511405214053140541405514056140571405814059140601406114062140631406414065140661406714068140691407014071140721407314074140751407614077140781407914080140811408214083140841408514086140871408814089140901409114092140931409414095140961409714098140991410014101141021410314104141051410614107141081410914110141111411214113141141411514116141171411814119141201412114122141231412414125141261412714128141291413014131141321413314134141351413614137141381413914140141411414214143141441414514146141471414814149141501415114152141531415414155141561415714158141591416014161141621416314164141651416614167141681416914170141711417214173141741417514176141771417814179141801418114182141831418414185141861418714188141891419014191141921419314194141951419614197141981419914200142011420214203142041420514206142071420814209142101421114212142131421414215142161421714218142191422014221142221422314224142251422614227142281422914230142311423214233142341423514236142371423814239142401424114242142431424414245142461424714248142491425014251142521425314254142551425614257142581425914260142611426214263142641426514266142671426814269142701427114272142731427414275142761427714278142791428014281142821428314284142851428614287142881428914290142911429214293142941429514296142971429814299143001430114302143031430414305143061430714308143091431014311143121431314314143151431614317143181431914320143211432214323143241432514326143271432814329143301433114332143331433414335143361433714338143391434014341143421434314344143451434614347143481434914350143511435214353143541435514356143571435814359143601436114362143631436414365143661436714368143691437014371143721437314374143751437614377143781437914380143811438214383143841438514386143871438814389143901439114392143931439414395143961439714398143991440014401144021440314404144051440614407144081440914410144111441214413144141441514416144171441814419144201442114422144231442414425144261442714428144291443014431144321443314434144351443614437144381443914440144411444214443144441444514446144471444814449144501445114452144531445414455144561445714458144591446014461144621446314464144651446614467144681446914470144711447214473144741447514476144771447814479144801448114482144831448414485144861448714488144891449014491144921449314494144951449614497144981449914500145011450214503145041450514506145071450814509145101451114512145131451414515145161451714518145191452014521145221452314524145251452614527145281452914530145311453214533145341453514536145371453814539145401454114542145431454414545145461454714548145491455014551145521455314554145551455614557145581455914560145611456214563145641456514566145671456814569145701457114572145731457414575145761457714578145791458014581145821458314584145851458614587145881458914590145911459214593145941459514596145971459814599146001460114602146031460414605146061460714608146091461014611146121461314614146151461614617146181461914620146211462214623146241462514626146271462814629146301463114632146331463414635146361463714638146391464014641146421464314644146451464614647146481464914650146511465214653146541465514656146571465814659146601466114662146631466414665146661466714668146691467014671146721467314674146751467614677146781467914680146811468214683146841468514686146871468814689146901469114692146931469414695146961469714698146991470014701147021470314704147051470614707147081470914710147111471214713147141471514716147171471814719147201472114722147231472414725147261472714728147291473014731147321473314734147351473614737147381473914740147411474214743147441474514746147471474814749147501475114752147531475414755147561475714758147591476014761147621476314764147651476614767147681476914770147711477214773147741477514776147771477814779147801478114782147831478414785147861478714788147891479014791147921479314794147951479614797147981479914800148011480214803148041480514806148071480814809148101481114812148131481414815148161481714818148191482014821148221482314824148251482614827148281482914830148311483214833148341483514836148371483814839148401484114842148431484414845148461484714848148491485014851148521485314854148551485614857148581485914860148611486214863148641486514866148671486814869148701487114872148731487414875148761487714878148791488014881148821488314884148851488614887148881488914890148911489214893148941489514896148971489814899149001490114902149031490414905149061490714908149091491014911149121491314914149151491614917149181491914920149211492214923149241492514926149271492814929149301493114932149331493414935149361493714938149391494014941149421494314944149451494614947149481494914950149511495214953149541495514956149571495814959149601496114962149631496414965149661496714968149691497014971149721497314974149751497614977149781497914980149811498214983149841498514986149871498814989149901499114992149931499414995149961499714998149991500015001150021500315004150051500615007150081500915010150111501215013150141501515016150171501815019150201502115022150231502415025150261502715028150291503015031150321503315034150351503615037150381503915040150411504215043150441504515046150471504815049150501505115052150531505415055150561505715058150591506015061150621506315064150651506615067150681506915070150711507215073150741507515076150771507815079150801508115082150831508415085150861508715088150891509015091150921509315094150951509615097150981509915100151011510215103151041510515106151071510815109151101511115112151131511415115151161511715118151191512015121151221512315124151251512615127151281512915130151311513215133151341513515136151371513815139151401514115142151431514415145151461514715148151491515015151151521515315154151551515615157151581515915160151611516215163151641516515166151671516815169151701517115172151731517415175151761517715178151791518015181151821518315184151851518615187151881518915190151911519215193151941519515196151971519815199152001520115202152031520415205152061520715208152091521015211152121521315214152151521615217152181521915220152211522215223152241522515226152271522815229152301523115232152331523415235152361523715238152391524015241152421524315244152451524615247152481524915250152511525215253152541525515256152571525815259152601526115262152631526415265152661526715268152691527015271152721527315274152751527615277152781527915280152811528215283152841528515286152871528815289152901529115292152931529415295152961529715298152991530015301153021530315304153051530615307153081530915310153111531215313153141531515316153171531815319153201532115322153231532415325153261532715328153291533015331153321533315334153351533615337153381533915340153411534215343153441534515346153471534815349153501535115352153531535415355153561535715358153591536015361153621536315364153651536615367153681536915370153711537215373153741537515376153771537815379153801538115382153831538415385153861538715388153891539015391153921539315394153951539615397153981539915400154011540215403154041540515406154071540815409154101541115412154131541415415154161541715418154191542015421154221542315424154251542615427154281542915430154311543215433154341543515436154371543815439154401544115442154431544415445154461544715448154491545015451154521545315454154551545615457154581545915460154611546215463154641546515466154671546815469154701547115472154731547415475154761547715478154791548015481154821548315484154851548615487154881548915490154911549215493154941549515496154971549815499155001550115502155031550415505155061550715508155091551015511155121551315514155151551615517155181551915520155211552215523155241552515526155271552815529155301553115532155331553415535155361553715538155391554015541155421554315544155451554615547155481554915550155511555215553155541555515556155571555815559155601556115562155631556415565155661556715568155691557015571155721557315574155751557615577155781557915580155811558215583155841558515586155871558815589155901559115592155931559415595155961559715598155991560015601156021560315604156051560615607156081560915610156111561215613156141561515616156171561815619156201562115622156231562415625156261562715628156291563015631156321563315634156351563615637156381563915640156411564215643156441564515646156471564815649156501565115652156531565415655156561565715658156591566015661156621566315664156651566615667156681566915670156711567215673156741567515676156771567815679156801568115682156831568415685156861568715688156891569015691156921569315694156951569615697156981569915700157011570215703157041570515706157071570815709157101571115712157131571415715157161571715718157191572015721157221572315724157251572615727157281572915730157311573215733157341573515736157371573815739157401574115742157431574415745157461574715748157491575015751157521575315754157551575615757157581575915760157611576215763157641576515766157671576815769157701577115772157731577415775157761577715778157791578015781157821578315784157851578615787157881578915790157911579215793157941579515796157971579815799158001580115802158031580415805158061580715808158091581015811158121581315814158151581615817158181581915820158211582215823158241582515826158271582815829158301583115832158331583415835158361583715838158391584015841158421584315844158451584615847158481584915850158511585215853158541585515856158571585815859158601586115862158631586415865158661586715868158691587015871158721587315874158751587615877158781587915880158811588215883158841588515886158871588815889158901589115892158931589415895158961589715898158991590015901159021590315904159051590615907159081590915910159111591215913159141591515916159171591815919159201592115922159231592415925159261592715928159291593015931159321593315934159351593615937159381593915940159411594215943159441594515946159471594815949159501595115952159531595415955159561595715958159591596015961159621596315964159651596615967159681596915970159711597215973159741597515976159771597815979159801598115982159831598415985159861598715988159891599015991159921599315994159951599615997159981599916000160011600216003160041600516006160071600816009160101601116012160131601416015160161601716018160191602016021160221602316024160251602616027160281602916030160311603216033160341603516036160371603816039160401604116042160431604416045160461604716048160491605016051160521605316054160551605616057160581605916060160611606216063160641606516066160671606816069160701607116072160731607416075160761607716078160791608016081160821608316084160851608616087160881608916090160911609216093160941609516096160971609816099161001610116102161031610416105161061610716108161091611016111161121611316114161151611616117161181611916120161211612216123161241612516126161271612816129161301613116132161331613416135161361613716138161391614016141161421614316144161451614616147161481614916150161511615216153161541615516156161571615816159161601616116162161631616416165161661616716168161691617016171161721617316174161751617616177161781617916180161811618216183161841618516186161871618816189161901619116192161931619416195161961619716198161991620016201162021620316204162051620616207162081620916210162111621216213162141621516216162171621816219162201622116222162231622416225162261622716228162291623016231162321623316234162351623616237162381623916240162411624216243162441624516246162471624816249162501625116252162531625416255162561625716258162591626016261162621626316264162651626616267162681626916270162711627216273162741627516276162771627816279162801628116282162831628416285162861628716288162891629016291162921629316294162951629616297162981629916300163011630216303163041630516306163071630816309163101631116312163131631416315163161631716318163191632016321163221632316324163251632616327163281632916330163311633216333163341633516336163371633816339163401634116342163431634416345163461634716348163491635016351163521635316354163551635616357163581635916360163611636216363163641636516366163671636816369163701637116372163731637416375163761637716378163791638016381163821638316384163851638616387163881638916390163911639216393163941639516396163971639816399164001640116402164031640416405164061640716408164091641016411164121641316414164151641616417164181641916420164211642216423164241642516426164271642816429164301643116432164331643416435164361643716438164391644016441164421644316444164451644616447164481644916450164511645216453164541645516456164571645816459164601646116462164631646416465164661646716468164691647016471164721647316474164751647616477164781647916480164811648216483164841648516486164871648816489164901649116492164931649416495164961649716498164991650016501165021650316504165051650616507165081650916510165111651216513165141651516516165171651816519165201652116522165231652416525165261652716528165291653016531165321653316534165351653616537165381653916540165411654216543165441654516546165471654816549165501655116552165531655416555165561655716558165591656016561165621656316564165651656616567165681656916570165711657216573165741657516576165771657816579165801658116582165831658416585165861658716588165891659016591165921659316594165951659616597165981659916600166011660216603166041660516606166071660816609166101661116612166131661416615166161661716618166191662016621166221662316624166251662616627166281662916630166311663216633166341663516636166371663816639166401664116642166431664416645166461664716648166491665016651166521665316654166551665616657166581665916660166611666216663166641666516666166671666816669166701667116672166731667416675166761667716678166791668016681166821668316684166851668616687166881668916690166911669216693166941669516696166971669816699167001670116702167031670416705167061670716708167091671016711167121671316714167151671616717167181671916720167211672216723167241672516726167271672816729167301673116732167331673416735167361673716738167391674016741167421674316744167451674616747167481674916750167511675216753167541675516756167571675816759167601676116762167631676416765167661676716768167691677016771167721677316774167751677616777167781677916780167811678216783167841678516786167871678816789167901679116792167931679416795167961679716798167991680016801168021680316804168051680616807168081680916810168111681216813168141681516816168171681816819168201682116822168231682416825168261682716828168291683016831168321683316834168351683616837168381683916840168411684216843168441684516846168471684816849168501685116852168531685416855168561685716858168591686016861168621686316864168651686616867168681686916870168711687216873168741687516876168771687816879168801688116882168831688416885168861688716888168891689016891168921689316894168951689616897168981689916900169011690216903169041690516906169071690816909169101691116912169131691416915169161691716918169191692016921169221692316924169251692616927169281692916930169311693216933169341693516936169371693816939169401694116942169431694416945169461694716948169491695016951169521695316954169551695616957169581695916960169611696216963169641696516966169671696816969169701697116972169731697416975169761697716978169791698016981169821698316984169851698616987169881698916990169911699216993169941699516996169971699816999170001700117002170031700417005170061700717008170091701017011170121701317014170151701617017170181701917020170211702217023170241702517026170271702817029170301703117032170331703417035170361703717038170391704017041170421704317044170451704617047170481704917050170511705217053170541705517056170571705817059170601706117062170631706417065170661706717068170691707017071170721707317074170751707617077170781707917080170811708217083170841708517086170871708817089170901709117092170931709417095170961709717098170991710017101171021710317104171051710617107171081710917110171111711217113171141711517116171171711817119171201712117122171231712417125171261712717128171291713017131171321713317134171351713617137171381713917140171411714217143171441714517146171471714817149171501715117152171531715417155171561715717158171591716017161171621716317164171651716617167171681716917170171711717217173171741717517176171771717817179171801718117182171831718417185171861718717188171891719017191171921719317194171951719617197171981719917200172011720217203172041720517206172071720817209172101721117212172131721417215172161721717218172191722017221172221722317224172251722617227172281722917230172311723217233172341723517236172371723817239172401724117242172431724417245172461724717248172491725017251172521725317254172551725617257172581725917260172611726217263172641726517266172671726817269172701727117272172731727417275172761727717278172791728017281172821728317284172851728617287172881728917290172911729217293172941729517296172971729817299173001730117302173031730417305173061730717308173091731017311173121731317314173151731617317173181731917320173211732217323173241732517326173271732817329173301733117332173331733417335173361733717338173391734017341173421734317344173451734617347173481734917350173511735217353173541735517356173571735817359173601736117362173631736417365173661736717368173691737017371173721737317374173751737617377173781737917380173811738217383173841738517386173871738817389173901739117392173931739417395173961739717398173991740017401174021740317404174051740617407174081740917410174111741217413174141741517416174171741817419174201742117422174231742417425174261742717428174291743017431174321743317434174351743617437174381743917440174411744217443174441744517446174471744817449174501745117452174531745417455174561745717458174591746017461174621746317464174651746617467174681746917470174711747217473174741747517476174771747817479174801748117482174831748417485174861748717488174891749017491174921749317494174951749617497174981749917500175011750217503175041750517506175071750817509175101751117512175131751417515175161751717518175191752017521175221752317524175251752617527175281752917530175311753217533175341753517536175371753817539175401754117542175431754417545175461754717548175491755017551175521755317554175551755617557175581755917560175611756217563175641756517566175671756817569175701757117572175731757417575175761757717578175791758017581175821758317584175851758617587175881758917590175911759217593175941759517596175971759817599176001760117602176031760417605176061760717608176091761017611176121761317614176151761617617176181761917620176211762217623176241762517626176271762817629176301763117632176331763417635176361763717638176391764017641176421764317644176451764617647176481764917650176511765217653176541765517656176571765817659176601766117662176631766417665176661766717668176691767017671176721767317674176751767617677176781767917680176811768217683176841768517686176871768817689176901769117692176931769417695176961769717698176991770017701177021770317704177051770617707177081770917710177111771217713177141771517716177171771817719177201772117722177231772417725177261772717728177291773017731177321773317734177351773617737177381773917740177411774217743177441774517746177471774817749177501775117752177531775417755177561775717758177591776017761177621776317764177651776617767177681776917770177711777217773177741777517776177771777817779177801778117782177831778417785177861778717788177891779017791177921779317794177951779617797177981779917800178011780217803178041780517806178071780817809178101781117812178131781417815178161781717818178191782017821178221782317824178251782617827178281782917830178311783217833178341783517836178371783817839178401784117842178431784417845178461784717848178491785017851178521785317854178551785617857178581785917860178611786217863178641786517866178671786817869178701787117872178731787417875178761787717878178791788017881178821788317884178851788617887178881788917890178911789217893178941789517896178971789817899179001790117902179031790417905179061790717908179091791017911179121791317914179151791617917179181791917920179211792217923179241792517926179271792817929179301793117932179331793417935179361793717938179391794017941179421794317944179451794617947179481794917950179511795217953179541795517956179571795817959179601796117962179631796417965179661796717968179691797017971179721797317974179751797617977179781797917980179811798217983179841798517986179871798817989179901799117992179931799417995179961799717998179991800018001180021800318004180051800618007180081800918010180111801218013180141801518016180171801818019180201802118022180231802418025180261802718028180291803018031180321803318034180351803618037180381803918040180411804218043180441804518046180471804818049180501805118052180531805418055180561805718058180591806018061180621806318064180651806618067180681806918070180711807218073180741807518076180771807818079180801808118082180831808418085180861808718088180891809018091180921809318094180951809618097180981809918100181011810218103181041810518106181071810818109181101811118112181131811418115181161811718118181191812018121181221812318124181251812618127181281812918130181311813218133181341813518136181371813818139181401814118142181431814418145181461814718148181491815018151181521815318154181551815618157181581815918160181611816218163181641816518166181671816818169181701817118172181731817418175181761817718178181791818018181181821818318184181851818618187181881818918190181911819218193181941819518196181971819818199182001820118202182031820418205182061820718208182091821018211182121821318214182151821618217182181821918220182211822218223182241822518226182271822818229182301823118232182331823418235182361823718238182391824018241182421824318244182451824618247182481824918250182511825218253182541825518256182571825818259182601826118262182631826418265182661826718268182691827018271182721827318274182751827618277182781827918280182811828218283182841828518286182871828818289182901829118292182931829418295182961829718298182991830018301183021830318304183051830618307183081830918310183111831218313183141831518316183171831818319183201832118322183231832418325183261832718328183291833018331183321833318334183351833618337183381833918340183411834218343183441834518346183471834818349183501835118352183531835418355183561835718358183591836018361183621836318364183651836618367183681836918370183711837218373183741837518376183771837818379183801838118382183831838418385183861838718388183891839018391183921839318394183951839618397183981839918400184011840218403184041840518406184071840818409184101841118412184131841418415184161841718418184191842018421184221842318424184251842618427184281842918430184311843218433184341843518436184371843818439184401844118442184431844418445184461844718448184491845018451184521845318454184551845618457184581845918460184611846218463184641846518466184671846818469184701847118472184731847418475184761847718478184791848018481184821848318484184851848618487184881848918490184911849218493184941849518496184971849818499185001850118502185031850418505185061850718508185091851018511185121851318514185151851618517185181851918520185211852218523185241852518526185271852818529185301853118532185331853418535185361853718538185391854018541185421854318544185451854618547185481854918550185511855218553185541855518556185571855818559185601856118562185631856418565185661856718568185691857018571185721857318574185751857618577185781857918580185811858218583185841858518586185871858818589185901859118592185931859418595185961859718598185991860018601186021860318604186051860618607186081860918610186111861218613186141861518616186171861818619186201862118622186231862418625186261862718628186291863018631186321863318634186351863618637186381863918640186411864218643186441864518646186471864818649186501865118652186531865418655186561865718658186591866018661186621866318664186651866618667186681866918670186711867218673186741867518676186771867818679186801868118682186831868418685186861868718688186891869018691186921869318694186951869618697186981869918700187011870218703187041870518706187071870818709187101871118712187131871418715187161871718718187191872018721187221872318724187251872618727187281872918730187311873218733187341873518736187371873818739187401874118742187431874418745187461874718748187491875018751187521875318754187551875618757187581875918760187611876218763187641876518766187671876818769187701877118772187731877418775187761877718778187791878018781187821878318784187851878618787187881878918790187911879218793187941879518796187971879818799188001880118802188031880418805188061880718808188091881018811188121881318814188151881618817188181881918820188211882218823188241882518826188271882818829188301883118832188331883418835188361883718838188391884018841188421884318844188451884618847188481884918850188511885218853188541885518856188571885818859188601886118862188631886418865188661886718868188691887018871188721887318874188751887618877188781887918880188811888218883188841888518886188871888818889188901889118892188931889418895188961889718898188991890018901189021890318904189051890618907189081890918910189111891218913189141891518916189171891818919189201892118922189231892418925189261892718928189291893018931189321893318934189351893618937189381893918940189411894218943189441894518946189471894818949189501895118952189531895418955189561895718958189591896018961189621896318964189651896618967189681896918970189711897218973189741897518976189771897818979189801898118982189831898418985189861898718988189891899018991189921899318994189951899618997189981899919000190011900219003190041900519006190071900819009190101901119012190131901419015190161901719018190191902019021190221902319024190251902619027190281902919030190311903219033190341903519036190371903819039190401904119042190431904419045190461904719048190491905019051190521905319054190551905619057190581905919060190611906219063190641906519066190671906819069190701907119072190731907419075190761907719078190791908019081190821908319084190851908619087190881908919090190911909219093190941909519096190971909819099191001910119102191031910419105191061910719108191091911019111191121911319114191151911619117191181911919120191211912219123191241912519126191271912819129191301913119132191331913419135191361913719138191391914019141191421914319144191451914619147191481914919150191511915219153191541915519156191571915819159191601916119162191631916419165191661916719168191691917019171191721917319174191751917619177191781917919180191811918219183191841918519186191871918819189191901919119192191931919419195191961919719198191991920019201192021920319204192051920619207192081920919210192111921219213192141921519216192171921819219192201922119222192231922419225192261922719228192291923019231192321923319234192351923619237192381923919240192411924219243192441924519246192471924819249192501925119252192531925419255192561925719258192591926019261192621926319264192651926619267192681926919270192711927219273192741927519276192771927819279192801928119282192831928419285192861928719288192891929019291192921929319294192951929619297192981929919300193011930219303193041930519306193071930819309193101931119312193131931419315193161931719318193191932019321193221932319324193251932619327193281932919330193311933219333193341933519336193371933819339193401934119342193431934419345193461934719348193491935019351193521935319354193551935619357193581935919360193611936219363193641936519366193671936819369193701937119372193731937419375193761937719378193791938019381193821938319384193851938619387193881938919390193911939219393193941939519396193971939819399194001940119402194031940419405194061940719408194091941019411194121941319414194151941619417194181941919420194211942219423194241942519426194271942819429194301943119432194331943419435194361943719438194391944019441194421944319444194451944619447194481944919450194511945219453194541945519456194571945819459194601946119462194631946419465194661946719468194691947019471194721947319474194751947619477194781947919480194811948219483194841948519486194871948819489194901949119492194931949419495194961949719498194991950019501195021950319504195051950619507195081950919510195111951219513195141951519516195171951819519195201952119522195231952419525195261952719528195291953019531195321953319534195351953619537195381953919540195411954219543195441954519546195471954819549195501955119552195531955419555195561955719558195591956019561195621956319564195651956619567195681956919570195711957219573195741957519576195771957819579195801958119582195831958419585195861958719588195891959019591195921959319594195951959619597195981959919600196011960219603196041960519606196071960819609196101961119612196131961419615196161961719618196191962019621196221962319624196251962619627196281962919630196311963219633196341963519636196371963819639196401964119642196431964419645196461964719648196491965019651196521965319654196551965619657196581965919660196611966219663196641966519666196671966819669196701967119672196731967419675196761967719678196791968019681196821968319684196851968619687196881968919690196911969219693196941969519696196971969819699197001970119702197031970419705197061970719708197091971019711197121971319714197151971619717197181971919720197211972219723197241972519726197271972819729197301973119732197331973419735197361973719738197391974019741197421974319744197451974619747197481974919750197511975219753197541975519756197571975819759197601976119762197631976419765197661976719768197691977019771197721977319774197751977619777197781977919780197811978219783197841978519786197871978819789197901979119792197931979419795197961979719798197991980019801198021980319804198051980619807198081980919810198111981219813198141981519816198171981819819198201982119822198231982419825198261982719828198291983019831198321983319834198351983619837198381983919840198411984219843198441984519846198471984819849198501985119852198531985419855198561985719858198591986019861198621986319864198651986619867198681986919870198711987219873198741987519876198771987819879198801988119882198831988419885198861988719888198891989019891198921989319894198951989619897198981989919900199011990219903199041990519906199071990819909199101991119912199131991419915199161991719918199191992019921199221992319924199251992619927199281992919930199311993219933199341993519936199371993819939199401994119942199431994419945199461994719948199491995019951199521995319954199551995619957199581995919960199611996219963199641996519966199671996819969199701997119972199731997419975199761997719978199791998019981199821998319984199851998619987199881998919990199911999219993199941999519996199971999819999200002000120002200032000420005200062000720008200092001020011200122001320014200152001620017200182001920020200212002220023200242002520026200272002820029200302003120032200332003420035200362003720038200392004020041200422004320044200452004620047200482004920050200512005220053200542005520056200572005820059200602006120062200632006420065200662006720068200692007020071200722007320074200752007620077200782007920080200812008220083200842008520086200872008820089200902009120092200932009420095200962009720098200992010020101201022010320104201052010620107201082010920110201112011220113201142011520116201172011820119201202012120122201232012420125201262012720128201292013020131201322013320134201352013620137201382013920140201412014220143201442014520146201472014820149201502015120152201532015420155201562015720158201592016020161201622016320164201652016620167201682016920170201712017220173201742017520176201772017820179201802018120182201832018420185201862018720188201892019020191201922019320194201952019620197201982019920200202012020220203202042020520206202072020820209202102021120212202132021420215202162021720218202192022020221202222022320224202252022620227202282022920230202312023220233202342023520236202372023820239202402024120242202432024420245202462024720248202492025020251202522025320254202552025620257202582025920260202612026220263202642026520266202672026820269202702027120272202732027420275202762027720278202792028020281202822028320284202852028620287202882028920290202912029220293202942029520296202972029820299203002030120302203032030420305203062030720308203092031020311203122031320314203152031620317203182031920320203212032220323203242032520326203272032820329203302033120332203332033420335203362033720338203392034020341203422034320344203452034620347203482034920350203512035220353203542035520356203572035820359203602036120362203632036420365203662036720368203692037020371203722037320374203752037620377203782037920380203812038220383203842038520386203872038820389203902039120392203932039420395203962039720398203992040020401204022040320404204052040620407204082040920410204112041220413204142041520416204172041820419204202042120422204232042420425204262042720428204292043020431204322043320434204352043620437204382043920440204412044220443204442044520446204472044820449204502045120452204532045420455204562045720458204592046020461204622046320464204652046620467204682046920470204712047220473204742047520476204772047820479204802048120482204832048420485204862048720488204892049020491204922049320494204952049620497204982049920500205012050220503205042050520506205072050820509205102051120512205132051420515205162051720518205192052020521205222052320524205252052620527205282052920530205312053220533205342053520536205372053820539205402054120542205432054420545205462054720548205492055020551205522055320554205552055620557205582055920560205612056220563205642056520566205672056820569205702057120572205732057420575205762057720578205792058020581205822058320584205852058620587205882058920590205912059220593205942059520596205972059820599206002060120602206032060420605206062060720608206092061020611206122061320614206152061620617206182061920620206212062220623206242062520626206272062820629206302063120632206332063420635206362063720638206392064020641206422064320644206452064620647206482064920650206512065220653206542065520656206572065820659206602066120662206632066420665206662066720668206692067020671206722067320674206752067620677206782067920680206812068220683206842068520686206872068820689206902069120692206932069420695206962069720698206992070020701207022070320704207052070620707207082070920710207112071220713207142071520716207172071820719207202072120722207232072420725207262072720728207292073020731207322073320734207352073620737207382073920740207412074220743207442074520746207472074820749207502075120752207532075420755207562075720758207592076020761207622076320764207652076620767207682076920770207712077220773207742077520776207772077820779207802078120782207832078420785207862078720788207892079020791207922079320794207952079620797207982079920800208012080220803208042080520806208072080820809208102081120812208132081420815208162081720818208192082020821208222082320824208252082620827208282082920830208312083220833208342083520836208372083820839208402084120842208432084420845208462084720848208492085020851208522085320854208552085620857208582085920860208612086220863208642086520866208672086820869208702087120872208732087420875208762087720878208792088020881208822088320884208852088620887208882088920890208912089220893208942089520896208972089820899209002090120902209032090420905209062090720908209092091020911209122091320914209152091620917209182091920920209212092220923209242092520926209272092820929209302093120932209332093420935209362093720938209392094020941209422094320944209452094620947209482094920950209512095220953209542095520956209572095820959209602096120962209632096420965209662096720968209692097020971209722097320974209752097620977209782097920980209812098220983209842098520986209872098820989209902099120992209932099420995209962099720998209992100021001210022100321004210052100621007210082100921010210112101221013210142101521016210172101821019210202102121022210232102421025210262102721028210292103021031210322103321034210352103621037210382103921040210412104221043210442104521046210472104821049210502105121052210532105421055210562105721058210592106021061210622106321064210652106621067210682106921070210712107221073210742107521076210772107821079210802108121082210832108421085210862108721088210892109021091210922109321094210952109621097210982109921100211012110221103211042110521106211072110821109211102111121112211132111421115211162111721118211192112021121211222112321124211252112621127211282112921130211312113221133211342113521136211372113821139211402114121142211432114421145211462114721148211492115021151211522115321154211552115621157211582115921160211612116221163211642116521166211672116821169211702117121172211732117421175211762117721178211792118021181211822118321184211852118621187211882118921190211912119221193211942119521196211972119821199212002120121202212032120421205212062120721208212092121021211212122121321214212152121621217212182121921220212212122221223212242122521226212272122821229212302123121232212332123421235212362123721238212392124021241212422124321244212452124621247212482124921250212512125221253212542125521256212572125821259212602126121262212632126421265212662126721268212692127021271212722127321274212752127621277212782127921280212812128221283212842128521286212872128821289212902129121292212932129421295212962129721298212992130021301213022130321304213052130621307213082130921310213112131221313213142131521316213172131821319213202132121322213232132421325213262132721328213292133021331213322133321334213352133621337213382133921340213412134221343213442134521346213472134821349213502135121352213532135421355213562135721358213592136021361213622136321364213652136621367213682136921370213712137221373213742137521376213772137821379213802138121382213832138421385213862138721388213892139021391213922139321394213952139621397213982139921400214012140221403214042140521406214072140821409214102141121412214132141421415214162141721418214192142021421214222142321424214252142621427214282142921430214312143221433214342143521436214372143821439214402144121442214432144421445214462144721448214492145021451214522145321454214552145621457214582145921460214612146221463214642146521466214672146821469214702147121472214732147421475214762147721478214792148021481214822148321484214852148621487214882148921490214912149221493214942149521496214972149821499215002150121502215032150421505215062150721508215092151021511215122151321514215152151621517215182151921520215212152221523215242152521526215272152821529215302153121532215332153421535215362153721538215392154021541215422154321544215452154621547215482154921550215512155221553215542155521556215572155821559215602156121562215632156421565215662156721568215692157021571215722157321574215752157621577215782157921580215812158221583215842158521586215872158821589215902159121592215932159421595215962159721598215992160021601216022160321604216052160621607216082160921610216112161221613216142161521616216172161821619216202162121622216232162421625216262162721628216292163021631216322163321634216352163621637216382163921640216412164221643216442164521646216472164821649216502165121652216532165421655216562165721658216592166021661216622166321664216652166621667216682166921670216712167221673216742167521676216772167821679216802168121682216832168421685216862168721688216892169021691216922169321694216952169621697216982169921700217012170221703217042170521706217072170821709217102171121712217132171421715217162171721718217192172021721217222172321724217252172621727217282172921730217312173221733217342173521736217372173821739217402174121742217432174421745217462174721748217492175021751217522175321754217552175621757217582175921760217612176221763217642176521766217672176821769217702177121772217732177421775217762177721778217792178021781217822178321784217852178621787217882178921790217912179221793217942179521796217972179821799218002180121802218032180421805218062180721808218092181021811218122181321814218152181621817218182181921820218212182221823218242182521826218272182821829218302183121832218332183421835218362183721838218392184021841218422184321844218452184621847218482184921850218512185221853218542185521856218572185821859218602186121862218632186421865218662186721868218692187021871218722187321874218752187621877218782187921880218812188221883218842188521886218872188821889218902189121892218932189421895218962189721898218992190021901219022190321904219052190621907219082190921910219112191221913219142191521916219172191821919219202192121922219232192421925219262192721928219292193021931219322193321934219352193621937219382193921940219412194221943219442194521946219472194821949219502195121952219532195421955219562195721958219592196021961219622196321964219652196621967219682196921970219712197221973219742197521976219772197821979219802198121982219832198421985219862198721988219892199021991219922199321994219952199621997219982199922000220012200222003220042200522006220072200822009220102201122012220132201422015220162201722018220192202022021220222202322024220252202622027220282202922030220312203222033220342203522036220372203822039220402204122042220432204422045220462204722048220492205022051220522205322054220552205622057220582205922060220612206222063220642206522066220672206822069220702207122072220732207422075220762207722078220792208022081220822208322084220852208622087220882208922090220912209222093220942209522096220972209822099221002210122102221032210422105221062210722108221092211022111221122211322114221152211622117221182211922120221212212222123221242212522126221272212822129221302213122132221332213422135221362213722138221392214022141221422214322144221452214622147221482214922150221512215222153221542215522156221572215822159221602216122162221632216422165221662216722168221692217022171221722217322174221752217622177221782217922180221812218222183221842218522186221872218822189221902219122192221932219422195221962219722198221992220022201222022220322204222052220622207222082220922210222112221222213222142221522216222172221822219222202222122222222232222422225222262222722228222292223022231222322223322234222352223622237222382223922240222412224222243222442224522246222472224822249222502225122252222532225422255222562225722258222592226022261222622226322264222652226622267222682226922270222712227222273222742227522276222772227822279222802228122282222832228422285222862228722288222892229022291222922229322294222952229622297222982229922300223012230222303223042230522306223072230822309223102231122312223132231422315223162231722318223192232022321223222232322324223252232622327223282232922330223312233222333223342233522336223372233822339223402234122342223432234422345223462234722348223492235022351223522235322354223552235622357223582235922360223612236222363223642236522366223672236822369223702237122372223732237422375223762237722378223792238022381223822238322384223852238622387223882238922390223912239222393223942239522396223972239822399224002240122402224032240422405224062240722408224092241022411224122241322414224152241622417224182241922420224212242222423224242242522426224272242822429224302243122432224332243422435224362243722438224392244022441224422244322444224452244622447224482244922450224512245222453224542245522456224572245822459224602246122462224632246422465224662246722468224692247022471224722247322474224752247622477224782247922480224812248222483224842248522486224872248822489224902249122492224932249422495224962249722498224992250022501225022250322504225052250622507225082250922510225112251222513225142251522516225172251822519225202252122522225232252422525225262252722528225292253022531225322253322534225352253622537225382253922540225412254222543225442254522546225472254822549225502255122552225532255422555225562255722558225592256022561225622256322564225652256622567225682256922570225712257222573225742257522576225772257822579225802258122582225832258422585225862258722588225892259022591225922259322594225952259622597225982259922600226012260222603226042260522606226072260822609226102261122612226132261422615226162261722618226192262022621226222262322624226252262622627226282262922630226312263222633226342263522636226372263822639226402264122642226432264422645226462264722648226492265022651226522265322654226552265622657226582265922660226612266222663226642266522666226672266822669226702267122672226732267422675226762267722678226792268022681226822268322684226852268622687226882268922690226912269222693226942269522696226972269822699227002270122702227032270422705227062270722708227092271022711227122271322714227152271622717227182271922720227212272222723227242272522726227272272822729227302273122732227332273422735227362273722738227392274022741227422274322744227452274622747227482274922750227512275222753227542275522756227572275822759227602276122762227632276422765227662276722768227692277022771227722277322774227752277622777227782277922780227812278222783227842278522786227872278822789227902279122792227932279422795227962279722798227992280022801228022280322804228052280622807228082280922810228112281222813228142281522816228172281822819228202282122822228232282422825228262282722828228292283022831228322283322834228352283622837228382283922840228412284222843228442284522846228472284822849228502285122852228532285422855228562285722858228592286022861228622286322864228652286622867228682286922870228712287222873228742287522876228772287822879228802288122882228832288422885228862288722888228892289022891228922289322894228952289622897228982289922900229012290222903229042290522906229072290822909229102291122912229132291422915229162291722918229192292022921229222292322924229252292622927229282292922930229312293222933229342293522936229372293822939229402294122942229432294422945229462294722948229492295022951229522295322954229552295622957229582295922960229612296222963229642296522966229672296822969229702297122972229732297422975229762297722978229792298022981229822298322984229852298622987229882298922990229912299222993229942299522996229972299822999230002300123002230032300423005230062300723008230092301023011230122301323014230152301623017230182301923020230212302223023230242302523026230272302823029230302303123032230332303423035230362303723038230392304023041230422304323044230452304623047230482304923050230512305223053230542305523056230572305823059230602306123062230632306423065230662306723068230692307023071230722307323074230752307623077230782307923080230812308223083230842308523086230872308823089230902309123092230932309423095230962309723098230992310023101231022310323104231052310623107231082310923110231112311223113231142311523116231172311823119231202312123122231232312423125231262312723128231292313023131231322313323134231352313623137231382313923140231412314223143231442314523146231472314823149231502315123152231532315423155231562315723158231592316023161231622316323164231652316623167231682316923170231712317223173231742317523176231772317823179231802318123182231832318423185231862318723188231892319023191231922319323194231952319623197231982319923200232012320223203232042320523206232072320823209232102321123212232132321423215232162321723218232192322023221232222322323224232252322623227232282322923230232312323223233232342323523236232372323823239232402324123242232432324423245232462324723248232492325023251232522325323254232552325623257232582325923260232612326223263232642326523266232672326823269232702327123272232732327423275232762327723278232792328023281232822328323284232852328623287232882328923290232912329223293232942329523296232972329823299233002330123302233032330423305233062330723308233092331023311233122331323314233152331623317233182331923320233212332223323233242332523326233272332823329233302333123332233332333423335233362333723338233392334023341233422334323344233452334623347233482334923350233512335223353233542335523356233572335823359233602336123362233632336423365233662336723368233692337023371233722337323374233752337623377233782337923380233812338223383233842338523386233872338823389233902339123392233932339423395233962339723398233992340023401234022340323404234052340623407234082340923410234112341223413234142341523416234172341823419234202342123422234232342423425234262342723428234292343023431234322343323434234352343623437234382343923440234412344223443234442344523446234472344823449234502345123452234532345423455234562345723458234592346023461234622346323464234652346623467234682346923470234712347223473234742347523476234772347823479234802348123482234832348423485234862348723488234892349023491234922349323494234952349623497234982349923500235012350223503235042350523506235072350823509235102351123512235132351423515235162351723518235192352023521235222352323524235252352623527235282352923530235312353223533235342353523536235372353823539235402354123542235432354423545235462354723548235492355023551235522355323554235552355623557235582355923560235612356223563235642356523566235672356823569235702357123572235732357423575235762357723578235792358023581235822358323584235852358623587235882358923590235912359223593235942359523596235972359823599236002360123602236032360423605236062360723608236092361023611236122361323614236152361623617236182361923620236212362223623236242362523626236272362823629236302363123632236332363423635236362363723638236392364023641236422364323644236452364623647236482364923650236512365223653236542365523656236572365823659236602366123662236632366423665236662366723668236692367023671236722367323674236752367623677236782367923680236812368223683236842368523686236872368823689236902369123692236932369423695236962369723698236992370023701237022370323704237052370623707237082370923710237112371223713237142371523716237172371823719237202372123722237232372423725237262372723728237292373023731237322373323734237352373623737237382373923740237412374223743237442374523746237472374823749237502375123752237532375423755237562375723758237592376023761237622376323764237652376623767237682376923770237712377223773237742377523776237772377823779237802378123782237832378423785237862378723788237892379023791237922379323794237952379623797237982379923800238012380223803238042380523806238072380823809238102381123812238132381423815238162381723818238192382023821238222382323824238252382623827238282382923830238312383223833238342383523836238372383823839238402384123842238432384423845238462384723848238492385023851238522385323854238552385623857238582385923860238612386223863238642386523866238672386823869238702387123872238732387423875238762387723878238792388023881238822388323884238852388623887238882388923890238912389223893238942389523896238972389823899239002390123902239032390423905239062390723908239092391023911239122391323914239152391623917239182391923920239212392223923239242392523926239272392823929239302393123932239332393423935239362393723938239392394023941239422394323944239452394623947239482394923950239512395223953239542395523956239572395823959239602396123962239632396423965239662396723968239692397023971239722397323974239752397623977239782397923980239812398223983239842398523986239872398823989239902399123992239932399423995239962399723998239992400024001240022400324004240052400624007240082400924010240112401224013240142401524016240172401824019240202402124022240232402424025240262402724028240292403024031240322403324034240352403624037240382403924040240412404224043240442404524046240472404824049240502405124052240532405424055240562405724058240592406024061240622406324064240652406624067240682406924070240712407224073240742407524076240772407824079240802408124082240832408424085240862408724088240892409024091240922409324094240952409624097240982409924100241012410224103241042410524106241072410824109241102411124112241132411424115241162411724118241192412024121241222412324124241252412624127241282412924130241312413224133241342413524136241372413824139241402414124142241432414424145241462414724148241492415024151241522415324154241552415624157241582415924160241612416224163241642416524166241672416824169241702417124172241732417424175241762417724178241792418024181241822418324184241852418624187241882418924190241912419224193241942419524196241972419824199242002420124202242032420424205242062420724208242092421024211242122421324214242152421624217242182421924220242212422224223242242422524226242272422824229242302423124232242332423424235242362423724238242392424024241242422424324244242452424624247242482424924250242512425224253242542425524256242572425824259242602426124262242632426424265242662426724268242692427024271242722427324274242752427624277242782427924280242812428224283242842428524286242872428824289242902429124292242932429424295242962429724298242992430024301243022430324304243052430624307243082430924310243112431224313243142431524316243172431824319243202432124322243232432424325243262432724328243292433024331243322433324334243352433624337243382433924340243412434224343243442434524346243472434824349243502435124352243532435424355243562435724358243592436024361243622436324364243652436624367243682436924370243712437224373243742437524376243772437824379243802438124382243832438424385243862438724388243892439024391243922439324394243952439624397243982439924400244012440224403244042440524406244072440824409244102441124412244132441424415244162441724418244192442024421244222442324424244252442624427244282442924430244312443224433244342443524436244372443824439244402444124442244432444424445244462444724448244492445024451244522445324454244552445624457244582445924460244612446224463244642446524466244672446824469244702447124472244732447424475244762447724478244792448024481244822448324484244852448624487244882448924490244912449224493244942449524496244972449824499245002450124502245032450424505245062450724508245092451024511245122451324514245152451624517245182451924520245212452224523245242452524526245272452824529245302453124532245332453424535245362453724538245392454024541245422454324544245452454624547245482454924550245512455224553245542455524556245572455824559245602456124562245632456424565245662456724568245692457024571245722457324574245752457624577245782457924580245812458224583245842458524586245872458824589245902459124592245932459424595245962459724598245992460024601246022460324604246052460624607246082460924610246112461224613246142461524616246172461824619246202462124622246232462424625246262462724628246292463024631246322463324634246352463624637246382463924640246412464224643246442464524646246472464824649246502465124652246532465424655246562465724658246592466024661246622466324664246652466624667246682466924670246712467224673246742467524676246772467824679246802468124682246832468424685246862468724688246892469024691246922469324694246952469624697246982469924700247012470224703247042470524706247072470824709247102471124712247132471424715247162471724718247192472024721247222472324724247252472624727247282472924730247312473224733247342473524736247372473824739247402474124742247432474424745247462474724748247492475024751247522475324754247552475624757247582475924760247612476224763247642476524766247672476824769247702477124772247732477424775247762477724778247792478024781247822478324784247852478624787247882478924790247912479224793247942479524796247972479824799248002480124802248032480424805248062480724808248092481024811248122481324814248152481624817248182481924820248212482224823248242482524826248272482824829248302483124832248332483424835248362483724838248392484024841248422484324844248452484624847248482484924850248512485224853248542485524856248572485824859248602486124862248632486424865248662486724868248692487024871248722487324874248752487624877248782487924880248812488224883248842488524886248872488824889248902489124892248932489424895248962489724898248992490024901249022490324904249052490624907249082490924910249112491224913249142491524916249172491824919249202492124922249232492424925249262492724928249292493024931249322493324934249352493624937249382493924940249412494224943249442494524946249472494824949249502495124952249532495424955249562495724958249592496024961249622496324964249652496624967249682496924970249712497224973249742497524976249772497824979249802498124982249832498424985249862498724988249892499024991249922499324994249952499624997249982499925000250012500225003250042500525006250072500825009250102501125012250132501425015250162501725018250192502025021250222502325024250252502625027250282502925030250312503225033250342503525036250372503825039250402504125042250432504425045250462504725048250492505025051250522505325054250552505625057250582505925060250612506225063250642506525066250672506825069250702507125072250732507425075250762507725078250792508025081250822508325084250852508625087250882508925090250912509225093250942509525096250972509825099251002510125102251032510425105251062510725108251092511025111251122511325114251152511625117251182511925120251212512225123251242512525126251272512825129251302513125132251332513425135251362513725138251392514025141251422514325144251452514625147251482514925150251512515225153251542515525156251572515825159251602516125162251632516425165251662516725168251692517025171251722517325174251752517625177251782517925180251812518225183251842518525186251872518825189251902519125192251932519425195251962519725198251992520025201252022520325204252052520625207252082520925210252112521225213252142521525216252172521825219252202522125222252232522425225252262522725228252292523025231252322523325234252352523625237252382523925240252412524225243252442524525246252472524825249252502525125252252532525425255252562525725258252592526025261252622526325264252652526625267252682526925270252712527225273252742527525276252772527825279252802528125282252832528425285252862528725288252892529025291252922529325294252952529625297252982529925300253012530225303253042530525306253072530825309253102531125312253132531425315253162531725318253192532025321253222532325324253252532625327253282532925330253312533225333253342533525336253372533825339253402534125342253432534425345253462534725348253492535025351253522535325354253552535625357253582535925360253612536225363253642536525366253672536825369253702537125372253732537425375253762537725378253792538025381253822538325384253852538625387253882538925390253912539225393253942539525396253972539825399254002540125402254032540425405254062540725408254092541025411254122541325414254152541625417254182541925420254212542225423254242542525426254272542825429254302543125432254332543425435254362543725438254392544025441254422544325444254452544625447254482544925450254512545225453254542545525456254572545825459254602546125462254632546425465254662546725468254692547025471254722547325474254752547625477254782547925480254812548225483254842548525486254872548825489254902549125492254932549425495254962549725498254992550025501255022550325504255052550625507255082550925510255112551225513255142551525516255172551825519255202552125522255232552425525255262552725528255292553025531255322553325534255352553625537255382553925540255412554225543255442554525546255472554825549255502555125552255532555425555255562555725558255592556025561255622556325564255652556625567255682556925570255712557225573255742557525576255772557825579255802558125582255832558425585255862558725588255892559025591255922559325594255952559625597255982559925600256012560225603256042560525606256072560825609256102561125612256132561425615256162561725618256192562025621256222562325624256252562625627256282562925630256312563225633256342563525636256372563825639256402564125642256432564425645256462564725648256492565025651256522565325654256552565625657256582565925660256612566225663256642566525666256672566825669256702567125672256732567425675256762567725678256792568025681256822568325684256852568625687256882568925690256912569225693256942569525696256972569825699257002570125702257032570425705257062570725708257092571025711257122571325714257152571625717257182571925720257212572225723257242572525726257272572825729257302573125732257332573425735257362573725738257392574025741257422574325744257452574625747257482574925750257512575225753257542575525756257572575825759257602576125762257632576425765257662576725768257692577025771257722577325774257752577625777257782577925780257812578225783257842578525786257872578825789257902579125792257932579425795257962579725798257992580025801258022580325804258052580625807258082580925810258112581225813258142581525816258172581825819258202582125822258232582425825258262582725828258292583025831258322583325834258352583625837258382583925840258412584225843258442584525846258472584825849258502585125852258532585425855258562585725858258592586025861258622586325864258652586625867258682586925870258712587225873258742587525876258772587825879258802588125882258832588425885258862588725888258892589025891258922589325894258952589625897258982589925900259012590225903259042590525906259072590825909259102591125912259132591425915259162591725918259192592025921259222592325924259252592625927259282592925930259312593225933259342593525936259372593825939259402594125942259432594425945259462594725948259492595025951259522595325954259552595625957259582595925960259612596225963259642596525966259672596825969259702597125972259732597425975259762597725978259792598025981259822598325984259852598625987259882598925990259912599225993259942599525996259972599825999260002600126002260032600426005260062600726008260092601026011260122601326014260152601626017260182601926020260212602226023260242602526026260272602826029260302603126032260332603426035260362603726038260392604026041260422604326044260452604626047260482604926050260512605226053260542605526056260572605826059260602606126062260632606426065260662606726068260692607026071260722607326074260752607626077260782607926080260812608226083260842608526086260872608826089260902609126092260932609426095260962609726098260992610026101261022610326104261052610626107261082610926110261112611226113261142611526116261172611826119261202612126122261232612426125261262612726128261292613026131261322613326134261352613626137261382613926140261412614226143261442614526146261472614826149261502615126152261532615426155261562615726158261592616026161261622616326164261652616626167261682616926170261712617226173261742617526176261772617826179261802618126182261832618426185261862618726188261892619026191261922619326194261952619626197261982619926200262012620226203262042620526206262072620826209262102621126212262132621426215262162621726218262192622026221262222622326224262252622626227262282622926230262312623226233262342623526236262372623826239262402624126242262432624426245262462624726248262492625026251262522625326254262552625626257262582625926260262612626226263262642626526266262672626826269262702627126272262732627426275262762627726278262792628026281262822628326284262852628626287262882628926290262912629226293262942629526296262972629826299263002630126302263032630426305263062630726308263092631026311263122631326314263152631626317263182631926320263212632226323263242632526326263272632826329263302633126332263332633426335263362633726338263392634026341263422634326344263452634626347263482634926350263512635226353263542635526356263572635826359263602636126362263632636426365263662636726368263692637026371263722637326374263752637626377263782637926380263812638226383263842638526386263872638826389263902639126392263932639426395263962639726398263992640026401264022640326404264052640626407264082640926410264112641226413264142641526416264172641826419264202642126422264232642426425264262642726428264292643026431264322643326434264352643626437264382643926440264412644226443264442644526446264472644826449264502645126452264532645426455264562645726458264592646026461264622646326464264652646626467264682646926470264712647226473264742647526476264772647826479264802648126482264832648426485264862648726488264892649026491264922649326494264952649626497264982649926500265012650226503265042650526506265072650826509265102651126512265132651426515265162651726518265192652026521265222652326524265252652626527265282652926530265312653226533265342653526536265372653826539265402654126542265432654426545265462654726548265492655026551265522655326554265552655626557265582655926560265612656226563265642656526566265672656826569265702657126572265732657426575265762657726578265792658026581265822658326584265852658626587265882658926590265912659226593265942659526596265972659826599266002660126602266032660426605266062660726608266092661026611266122661326614266152661626617266182661926620266212662226623266242662526626266272662826629266302663126632266332663426635266362663726638266392664026641266422664326644266452664626647266482664926650266512665226653266542665526656266572665826659266602666126662266632666426665266662666726668266692667026671266722667326674266752667626677266782667926680266812668226683266842668526686266872668826689266902669126692266932669426695266962669726698266992670026701267022670326704267052670626707267082670926710267112671226713267142671526716267172671826719267202672126722267232672426725267262672726728267292673026731267322673326734267352673626737267382673926740267412674226743267442674526746267472674826749267502675126752267532675426755267562675726758267592676026761267622676326764267652676626767267682676926770267712677226773267742677526776267772677826779267802678126782267832678426785267862678726788267892679026791267922679326794267952679626797267982679926800268012680226803268042680526806268072680826809268102681126812268132681426815268162681726818268192682026821268222682326824268252682626827268282682926830268312683226833268342683526836268372683826839268402684126842268432684426845268462684726848268492685026851268522685326854268552685626857268582685926860268612686226863268642686526866268672686826869268702687126872268732687426875268762687726878268792688026881268822688326884268852688626887268882688926890268912689226893268942689526896268972689826899269002690126902269032690426905269062690726908269092691026911269122691326914269152691626917269182691926920269212692226923269242692526926269272692826929269302693126932269332693426935269362693726938269392694026941269422694326944269452694626947269482694926950269512695226953269542695526956269572695826959269602696126962269632696426965269662696726968269692697026971269722697326974269752697626977269782697926980269812698226983269842698526986269872698826989269902699126992269932699426995269962699726998269992700027001270022700327004270052700627007270082700927010270112701227013270142701527016270172701827019270202702127022270232702427025270262702727028270292703027031270322703327034270352703627037270382703927040270412704227043270442704527046270472704827049270502705127052270532705427055270562705727058270592706027061270622706327064270652706627067270682706927070270712707227073270742707527076270772707827079270802708127082270832708427085270862708727088270892709027091270922709327094270952709627097270982709927100271012710227103271042710527106271072710827109271102711127112271132711427115271162711727118271192712027121271222712327124271252712627127271282712927130271312713227133271342713527136271372713827139271402714127142271432714427145271462714727148271492715027151271522715327154271552715627157271582715927160271612716227163271642716527166271672716827169271702717127172271732717427175271762717727178271792718027181271822718327184271852718627187271882718927190271912719227193271942719527196271972719827199272002720127202272032720427205272062720727208272092721027211272122721327214272152721627217272182721927220272212722227223272242722527226272272722827229272302723127232272332723427235272362723727238272392724027241272422724327244272452724627247272482724927250272512725227253272542725527256272572725827259272602726127262272632726427265272662726727268272692727027271272722727327274272752727627277272782727927280272812728227283272842728527286272872728827289272902729127292272932729427295272962729727298272992730027301273022730327304273052730627307273082730927310273112731227313273142731527316273172731827319273202732127322273232732427325273262732727328273292733027331273322733327334273352733627337273382733927340273412734227343273442734527346273472734827349273502735127352273532735427355273562735727358273592736027361273622736327364273652736627367273682736927370273712737227373273742737527376273772737827379273802738127382273832738427385273862738727388273892739027391273922739327394273952739627397273982739927400274012740227403274042740527406274072740827409274102741127412274132741427415274162741727418274192742027421274222742327424274252742627427274282742927430274312743227433274342743527436274372743827439274402744127442274432744427445274462744727448274492745027451274522745327454274552745627457274582745927460274612746227463274642746527466274672746827469274702747127472274732747427475274762747727478274792748027481274822748327484274852748627487274882748927490274912749227493274942749527496274972749827499275002750127502275032750427505275062750727508275092751027511275122751327514275152751627517275182751927520275212752227523275242752527526275272752827529275302753127532275332753427535275362753727538275392754027541275422754327544275452754627547275482754927550275512755227553275542755527556275572755827559275602756127562275632756427565275662756727568275692757027571275722757327574275752757627577275782757927580275812758227583275842758527586275872758827589275902759127592275932759427595275962759727598275992760027601276022760327604276052760627607276082760927610276112761227613276142761527616276172761827619276202762127622276232762427625276262762727628276292763027631276322763327634276352763627637276382763927640276412764227643276442764527646276472764827649276502765127652276532765427655276562765727658276592766027661276622766327664276652766627667276682766927670276712767227673276742767527676276772767827679276802768127682276832768427685276862768727688276892769027691276922769327694276952769627697276982769927700277012770227703277042770527706277072770827709277102771127712277132771427715277162771727718277192772027721277222772327724277252772627727277282772927730277312773227733277342773527736277372773827739277402774127742277432774427745277462774727748277492775027751277522775327754277552775627757277582775927760277612776227763277642776527766277672776827769277702777127772277732777427775277762777727778277792778027781277822778327784277852778627787277882778927790277912779227793277942779527796277972779827799278002780127802278032780427805278062780727808278092781027811278122781327814278152781627817278182781927820278212782227823278242782527826278272782827829278302783127832278332783427835278362783727838278392784027841278422784327844278452784627847278482784927850278512785227853278542785527856278572785827859278602786127862278632786427865278662786727868278692787027871278722787327874278752787627877278782787927880278812788227883278842788527886278872788827889278902789127892278932789427895278962789727898278992790027901279022790327904279052790627907279082790927910279112791227913279142791527916279172791827919279202792127922279232792427925279262792727928279292793027931279322793327934279352793627937279382793927940279412794227943279442794527946279472794827949279502795127952279532795427955279562795727958279592796027961279622796327964279652796627967279682796927970279712797227973279742797527976279772797827979279802798127982279832798427985279862798727988279892799027991279922799327994279952799627997279982799928000280012800228003280042800528006280072800828009280102801128012280132801428015280162801728018280192802028021280222802328024280252802628027280282802928030280312803228033280342803528036280372803828039280402804128042280432804428045280462804728048280492805028051280522805328054280552805628057280582805928060280612806228063280642806528066280672806828069280702807128072280732807428075280762807728078280792808028081280822808328084280852808628087280882808928090280912809228093280942809528096280972809828099281002810128102281032810428105281062810728108281092811028111281122811328114281152811628117281182811928120281212812228123281242812528126281272812828129281302813128132281332813428135281362813728138281392814028141281422814328144281452814628147281482814928150281512815228153281542815528156281572815828159281602816128162281632816428165281662816728168281692817028171281722817328174281752817628177281782817928180281812818228183281842818528186281872818828189281902819128192281932819428195281962819728198281992820028201282022820328204282052820628207282082820928210282112821228213282142821528216282172821828219282202822128222282232822428225282262822728228282292823028231282322823328234282352823628237282382823928240282412824228243282442824528246282472824828249282502825128252282532825428255282562825728258282592826028261282622826328264282652826628267282682826928270282712827228273282742827528276282772827828279282802828128282282832828428285282862828728288282892829028291282922829328294282952829628297282982829928300283012830228303283042830528306283072830828309283102831128312283132831428315283162831728318283192832028321283222832328324283252832628327283282832928330283312833228333283342833528336283372833828339283402834128342283432834428345283462834728348283492835028351283522835328354283552835628357283582835928360283612836228363283642836528366283672836828369283702837128372283732837428375283762837728378283792838028381283822838328384283852838628387283882838928390283912839228393283942839528396283972839828399284002840128402284032840428405284062840728408284092841028411284122841328414284152841628417284182841928420284212842228423284242842528426284272842828429284302843128432284332843428435284362843728438284392844028441284422844328444284452844628447284482844928450284512845228453284542845528456284572845828459284602846128462284632846428465284662846728468284692847028471284722847328474284752847628477284782847928480284812848228483284842848528486284872848828489284902849128492284932849428495284962849728498284992850028501285022850328504285052850628507285082850928510285112851228513285142851528516285172851828519285202852128522285232852428525285262852728528285292853028531285322853328534285352853628537285382853928540285412854228543285442854528546285472854828549285502855128552285532855428555285562855728558285592856028561285622856328564285652856628567285682856928570285712857228573285742857528576285772857828579285802858128582285832858428585285862858728588285892859028591285922859328594285952859628597285982859928600286012860228603286042860528606286072860828609286102861128612286132861428615286162861728618286192862028621286222862328624286252862628627286282862928630286312863228633286342863528636286372863828639286402864128642286432864428645286462864728648286492865028651286522865328654286552865628657286582865928660286612866228663286642866528666286672866828669286702867128672286732867428675286762867728678286792868028681286822868328684286852868628687286882868928690286912869228693286942869528696286972869828699287002870128702287032870428705287062870728708287092871028711287122871328714287152871628717287182871928720287212872228723287242872528726287272872828729287302873128732287332873428735287362873728738287392874028741287422874328744287452874628747287482874928750287512875228753287542875528756287572875828759287602876128762287632876428765287662876728768287692877028771287722877328774287752877628777287782877928780287812878228783287842878528786287872878828789287902879128792287932879428795287962879728798287992880028801288022880328804288052880628807288082880928810288112881228813288142881528816288172881828819288202882128822288232882428825288262882728828288292883028831288322883328834288352883628837288382883928840288412884228843288442884528846288472884828849288502885128852288532885428855288562885728858288592886028861288622886328864288652886628867288682886928870288712887228873288742887528876288772887828879288802888128882288832888428885288862888728888288892889028891288922889328894288952889628897288982889928900289012890228903289042890528906289072890828909289102891128912289132891428915289162891728918289192892028921289222892328924289252892628927289282892928930289312893228933289342893528936289372893828939289402894128942289432894428945289462894728948289492895028951289522895328954289552895628957289582895928960289612896228963289642896528966289672896828969289702897128972289732897428975289762897728978289792898028981289822898328984289852898628987289882898928990289912899228993289942899528996289972899828999290002900129002290032900429005290062900729008290092901029011290122901329014290152901629017290182901929020290212902229023290242902529026290272902829029290302903129032290332903429035290362903729038290392904029041290422904329044290452904629047290482904929050290512905229053290542905529056290572905829059290602906129062290632906429065290662906729068290692907029071290722907329074290752907629077290782907929080290812908229083290842908529086290872908829089290902909129092290932909429095290962909729098290992910029101291022910329104291052910629107291082910929110291112911229113291142911529116291172911829119291202912129122291232912429125291262912729128291292913029131291322913329134291352913629137291382913929140291412914229143291442914529146291472914829149291502915129152291532915429155291562915729158291592916029161291622916329164291652916629167291682916929170291712917229173291742917529176291772917829179291802918129182291832918429185291862918729188291892919029191291922919329194291952919629197291982919929200292012920229203292042920529206292072920829209292102921129212292132921429215292162921729218292192922029221292222922329224292252922629227292282922929230292312923229233292342923529236292372923829239292402924129242292432924429245292462924729248292492925029251292522925329254292552925629257292582925929260292612926229263292642926529266292672926829269292702927129272292732927429275292762927729278292792928029281292822928329284292852928629287292882928929290292912929229293292942929529296292972929829299293002930129302293032930429305293062930729308293092931029311293122931329314293152931629317293182931929320293212932229323293242932529326293272932829329293302933129332293332933429335293362933729338293392934029341293422934329344293452934629347293482934929350293512935229353293542935529356293572935829359293602936129362293632936429365293662936729368293692937029371293722937329374293752937629377293782937929380293812938229383293842938529386293872938829389293902939129392293932939429395293962939729398293992940029401294022940329404294052940629407294082940929410294112941229413294142941529416294172941829419294202942129422294232942429425294262942729428294292943029431294322943329434294352943629437294382943929440294412944229443294442944529446294472944829449294502945129452294532945429455294562945729458294592946029461294622946329464294652946629467294682946929470294712947229473294742947529476294772947829479294802948129482294832948429485294862948729488294892949029491294922949329494294952949629497294982949929500295012950229503295042950529506295072950829509295102951129512295132951429515295162951729518295192952029521295222952329524295252952629527295282952929530295312953229533295342953529536295372953829539295402954129542295432954429545295462954729548295492955029551295522955329554295552955629557295582955929560295612956229563295642956529566295672956829569295702957129572295732957429575295762957729578295792958029581295822958329584295852958629587295882958929590295912959229593295942959529596295972959829599296002960129602296032960429605296062960729608296092961029611296122961329614296152961629617296182961929620296212962229623296242962529626296272962829629296302963129632296332963429635296362963729638296392964029641296422964329644296452964629647296482964929650296512965229653296542965529656296572965829659296602966129662296632966429665296662966729668296692967029671296722967329674296752967629677296782967929680296812968229683296842968529686296872968829689296902969129692296932969429695296962969729698296992970029701297022970329704297052970629707297082970929710297112971229713297142971529716297172971829719297202972129722297232972429725297262972729728297292973029731297322973329734297352973629737297382973929740297412974229743297442974529746297472974829749297502975129752297532975429755297562975729758297592976029761297622976329764297652976629767297682976929770297712977229773297742977529776297772977829779297802978129782297832978429785297862978729788297892979029791297922979329794297952979629797297982979929800298012980229803298042980529806298072980829809298102981129812298132981429815298162981729818298192982029821298222982329824298252982629827298282982929830298312983229833298342983529836298372983829839298402984129842298432984429845298462984729848298492985029851298522985329854298552985629857298582985929860298612986229863298642986529866298672986829869298702987129872298732987429875298762987729878298792988029881298822988329884298852988629887298882988929890298912989229893298942989529896298972989829899299002990129902299032990429905299062990729908299092991029911299122991329914299152991629917299182991929920299212992229923299242992529926299272992829929299302993129932299332993429935299362993729938299392994029941299422994329944299452994629947299482994929950299512995229953299542995529956299572995829959299602996129962299632996429965299662996729968299692997029971299722997329974299752997629977299782997929980299812998229983299842998529986299872998829989299902999129992299932999429995299962999729998299993000030001300023000330004300053000630007300083000930010300113001230013300143001530016300173001830019300203002130022300233002430025300263002730028300293003030031300323003330034300353003630037300383003930040300413004230043300443004530046300473004830049300503005130052300533005430055300563005730058300593006030061300623006330064300653006630067300683006930070300713007230073300743007530076300773007830079300803008130082300833008430085300863008730088300893009030091300923009330094300953009630097300983009930100301013010230103301043010530106301073010830109301103011130112301133011430115301163011730118301193012030121301223012330124301253012630127301283012930130301313013230133301343013530136301373013830139301403014130142301433014430145301463014730148301493015030151301523015330154301553015630157301583015930160301613016230163301643016530166301673016830169301703017130172301733017430175301763017730178301793018030181301823018330184301853018630187301883018930190301913019230193301943019530196301973019830199302003020130202302033020430205302063020730208302093021030211302123021330214302153021630217302183021930220302213022230223302243022530226302273022830229302303023130232302333023430235302363023730238302393024030241302423024330244302453024630247302483024930250302513025230253302543025530256302573025830259302603026130262302633026430265302663026730268302693027030271302723027330274302753027630277302783027930280302813028230283302843028530286302873028830289302903029130292302933029430295302963029730298302993030030301303023030330304303053030630307303083030930310303113031230313303143031530316303173031830319303203032130322303233032430325303263032730328303293033030331303323033330334303353033630337303383033930340303413034230343303443034530346303473034830349303503035130352303533035430355303563035730358303593036030361303623036330364303653036630367303683036930370303713037230373303743037530376303773037830379303803038130382303833038430385303863038730388303893039030391303923039330394303953039630397303983039930400304013040230403304043040530406304073040830409304103041130412304133041430415304163041730418304193042030421304223042330424304253042630427304283042930430304313043230433304343043530436304373043830439304403044130442304433044430445304463044730448304493045030451304523045330454304553045630457304583045930460304613046230463304643046530466304673046830469304703047130472304733047430475304763047730478304793048030481304823048330484304853048630487304883048930490304913049230493304943049530496304973049830499305003050130502305033050430505305063050730508305093051030511305123051330514305153051630517305183051930520305213052230523305243052530526305273052830529305303053130532305333053430535305363053730538305393054030541305423054330544305453054630547305483054930550305513055230553305543055530556305573055830559305603056130562305633056430565305663056730568305693057030571305723057330574305753057630577305783057930580305813058230583305843058530586305873058830589305903059130592305933059430595305963059730598305993060030601306023060330604306053060630607306083060930610306113061230613306143061530616306173061830619306203062130622306233062430625306263062730628306293063030631306323063330634306353063630637306383063930640306413064230643306443064530646306473064830649306503065130652306533065430655306563065730658306593066030661306623066330664306653066630667306683066930670306713067230673306743067530676306773067830679306803068130682306833068430685306863068730688306893069030691306923069330694306953069630697306983069930700307013070230703307043070530706307073070830709307103071130712307133071430715307163071730718307193072030721307223072330724307253072630727307283072930730307313073230733307343073530736307373073830739307403074130742307433074430745307463074730748307493075030751307523075330754307553075630757307583075930760307613076230763307643076530766307673076830769307703077130772307733077430775307763077730778307793078030781307823078330784307853078630787307883078930790307913079230793307943079530796307973079830799308003080130802308033080430805308063080730808308093081030811308123081330814308153081630817308183081930820308213082230823308243082530826308273082830829308303083130832308333083430835308363083730838308393084030841308423084330844308453084630847308483084930850308513085230853308543085530856308573085830859308603086130862308633086430865308663086730868308693087030871308723087330874308753087630877308783087930880308813088230883308843088530886308873088830889308903089130892308933089430895308963089730898308993090030901309023090330904309053090630907309083090930910309113091230913309143091530916309173091830919309203092130922309233092430925309263092730928309293093030931309323093330934309353093630937309383093930940309413094230943309443094530946309473094830949309503095130952309533095430955309563095730958309593096030961309623096330964309653096630967309683096930970309713097230973309743097530976309773097830979309803098130982309833098430985309863098730988309893099030991309923099330994309953099630997309983099931000310013100231003310043100531006310073100831009310103101131012310133101431015310163101731018310193102031021310223102331024310253102631027310283102931030310313103231033310343103531036310373103831039310403104131042310433104431045310463104731048310493105031051310523105331054310553105631057310583105931060310613106231063310643106531066310673106831069310703107131072310733107431075310763107731078310793108031081310823108331084310853108631087310883108931090310913109231093310943109531096310973109831099311003110131102311033110431105311063110731108311093111031111311123111331114311153111631117311183111931120311213112231123311243112531126311273112831129311303113131132311333113431135311363113731138311393114031141311423114331144311453114631147311483114931150311513115231153311543115531156311573115831159311603116131162311633116431165311663116731168311693117031171311723117331174311753117631177311783117931180311813118231183311843118531186311873118831189311903119131192311933119431195311963119731198311993120031201312023120331204312053120631207312083120931210312113121231213312143121531216312173121831219312203122131222312233122431225312263122731228312293123031231312323123331234312353123631237312383123931240312413124231243312443124531246312473124831249312503125131252312533125431255312563125731258312593126031261312623126331264312653126631267312683126931270312713127231273312743127531276312773127831279312803128131282312833128431285312863128731288312893129031291312923129331294312953129631297312983129931300313013130231303313043130531306313073130831309313103131131312313133131431315313163131731318313193132031321313223132331324313253132631327313283132931330313313133231333313343133531336313373133831339313403134131342313433134431345313463134731348313493135031351313523135331354313553135631357313583135931360313613136231363313643136531366313673136831369313703137131372313733137431375313763137731378313793138031381313823138331384313853138631387313883138931390313913139231393313943139531396313973139831399314003140131402314033140431405314063140731408314093141031411314123141331414314153141631417314183141931420314213142231423314243142531426314273142831429314303143131432314333143431435314363143731438314393144031441314423144331444314453144631447314483144931450314513145231453314543145531456314573145831459314603146131462314633146431465314663146731468314693147031471314723147331474314753147631477314783147931480314813148231483314843148531486314873148831489314903149131492314933149431495314963149731498314993150031501315023150331504315053150631507315083150931510315113151231513315143151531516315173151831519315203152131522315233152431525315263152731528315293153031531315323153331534315353153631537315383153931540315413154231543315443154531546315473154831549315503155131552315533155431555315563155731558315593156031561315623156331564315653156631567315683156931570315713157231573315743157531576315773157831579315803158131582315833158431585315863158731588315893159031591315923159331594315953159631597315983159931600316013160231603316043160531606316073160831609316103161131612316133161431615316163161731618316193162031621316223162331624316253162631627316283162931630316313163231633316343163531636316373163831639316403164131642316433164431645316463164731648316493165031651316523165331654316553165631657316583165931660316613166231663316643166531666316673166831669316703167131672316733167431675316763167731678316793168031681316823168331684316853168631687316883168931690316913169231693316943169531696316973169831699317003170131702317033170431705317063170731708317093171031711317123171331714317153171631717317183171931720317213172231723317243172531726317273172831729317303173131732317333173431735317363173731738317393174031741317423174331744317453174631747317483174931750317513175231753317543175531756317573175831759317603176131762317633176431765317663176731768317693177031771317723177331774317753177631777317783177931780317813178231783317843178531786317873178831789317903179131792317933179431795317963179731798317993180031801318023180331804318053180631807318083180931810318113181231813318143181531816318173181831819318203182131822318233182431825318263182731828318293183031831318323183331834318353183631837318383183931840318413184231843318443184531846318473184831849318503185131852318533185431855318563185731858318593186031861318623186331864318653186631867318683186931870318713187231873318743187531876318773187831879318803188131882318833188431885318863188731888318893189031891318923189331894318953189631897318983189931900319013190231903319043190531906319073190831909319103191131912319133191431915319163191731918319193192031921319223192331924319253192631927319283192931930319313193231933319343193531936319373193831939319403194131942319433194431945319463194731948319493195031951319523195331954319553195631957319583195931960319613196231963319643196531966319673196831969319703197131972319733197431975319763197731978319793198031981319823198331984319853198631987319883198931990319913199231993319943199531996319973199831999320003200132002320033200432005320063200732008320093201032011320123201332014320153201632017320183201932020320213202232023320243202532026320273202832029320303203132032320333203432035320363203732038320393204032041320423204332044320453204632047320483204932050320513205232053320543205532056320573205832059320603206132062320633206432065320663206732068320693207032071320723207332074320753207632077320783207932080320813208232083320843208532086320873208832089320903209132092320933209432095320963209732098320993210032101321023210332104321053210632107321083210932110321113211232113321143211532116321173211832119321203212132122321233212432125321263212732128321293213032131321323213332134321353213632137321383213932140321413214232143321443214532146321473214832149321503215132152321533215432155321563215732158321593216032161321623216332164321653216632167321683216932170321713217232173321743217532176321773217832179321803218132182321833218432185321863218732188321893219032191321923219332194321953219632197321983219932200322013220232203322043220532206322073220832209322103221132212322133221432215322163221732218322193222032221322223222332224322253222632227322283222932230322313223232233322343223532236322373223832239322403224132242322433224432245322463224732248322493225032251322523225332254322553225632257322583225932260322613226232263322643226532266322673226832269322703227132272322733227432275322763227732278322793228032281322823228332284322853228632287322883228932290322913229232293322943229532296322973229832299323003230132302323033230432305323063230732308323093231032311323123231332314323153231632317323183231932320323213232232323323243232532326323273232832329323303233132332323333233432335323363233732338323393234032341323423234332344323453234632347323483234932350323513235232353323543235532356323573235832359323603236132362323633236432365323663236732368323693237032371323723237332374323753237632377323783237932380323813238232383323843238532386323873238832389323903239132392323933239432395323963239732398323993240032401324023240332404324053240632407324083240932410324113241232413324143241532416324173241832419324203242132422324233242432425324263242732428324293243032431324323243332434324353243632437324383243932440324413244232443324443244532446324473244832449324503245132452324533245432455324563245732458324593246032461324623246332464324653246632467324683246932470324713247232473324743247532476324773247832479324803248132482324833248432485324863248732488324893249032491324923249332494324953249632497324983249932500325013250232503325043250532506325073250832509325103251132512325133251432515325163251732518325193252032521325223252332524325253252632527325283252932530325313253232533325343253532536325373253832539325403254132542325433254432545325463254732548325493255032551325523255332554325553255632557325583255932560325613256232563325643256532566325673256832569325703257132572325733257432575325763257732578325793258032581325823258332584325853258632587325883258932590325913259232593325943259532596325973259832599326003260132602326033260432605326063260732608326093261032611326123261332614326153261632617326183261932620326213262232623326243262532626326273262832629326303263132632326333263432635326363263732638326393264032641326423264332644326453264632647326483264932650326513265232653326543265532656326573265832659326603266132662326633266432665326663266732668326693267032671326723267332674326753267632677326783267932680326813268232683326843268532686326873268832689326903269132692326933269432695326963269732698326993270032701327023270332704327053270632707327083270932710327113271232713327143271532716327173271832719327203272132722327233272432725327263272732728327293273032731327323273332734327353273632737327383273932740327413274232743327443274532746327473274832749327503275132752327533275432755327563275732758327593276032761327623276332764327653276632767327683276932770327713277232773327743277532776327773277832779327803278132782327833278432785327863278732788327893279032791327923279332794327953279632797327983279932800328013280232803328043280532806328073280832809328103281132812328133281432815328163281732818328193282032821328223282332824328253282632827328283282932830328313283232833328343283532836328373283832839328403284132842328433284432845328463284732848328493285032851328523285332854328553285632857328583285932860328613286232863328643286532866328673286832869328703287132872328733287432875328763287732878328793288032881328823288332884328853288632887328883288932890328913289232893328943289532896328973289832899329003290132902329033290432905329063290732908329093291032911329123291332914329153291632917329183291932920329213292232923329243292532926329273292832929329303293132932329333293432935329363293732938329393294032941329423294332944329453294632947329483294932950329513295232953329543295532956329573295832959329603296132962329633296432965329663296732968329693297032971329723297332974329753297632977329783297932980329813298232983329843298532986329873298832989329903299132992329933299432995329963299732998329993300033001330023300333004330053300633007330083300933010330113301233013330143301533016330173301833019330203302133022330233302433025330263302733028330293303033031330323303333034330353303633037330383303933040330413304233043330443304533046330473304833049330503305133052330533305433055330563305733058330593306033061330623306333064330653306633067330683306933070330713307233073330743307533076330773307833079330803308133082330833308433085330863308733088330893309033091330923309333094330953309633097330983309933100331013310233103331043310533106331073310833109331103311133112331133311433115331163311733118331193312033121331223312333124331253312633127331283312933130331313313233133331343313533136331373313833139331403314133142331433314433145331463314733148331493315033151331523315333154331553315633157331583315933160331613316233163331643316533166331673316833169331703317133172331733317433175331763317733178331793318033181331823318333184331853318633187331883318933190331913319233193331943319533196331973319833199332003320133202332033320433205332063320733208332093321033211332123321333214332153321633217332183321933220332213322233223332243322533226332273322833229332303323133232332333323433235332363323733238332393324033241332423324333244332453324633247332483324933250332513325233253332543325533256332573325833259332603326133262332633326433265332663326733268332693327033271332723327333274332753327633277332783327933280332813328233283332843328533286332873328833289332903329133292332933329433295332963329733298332993330033301333023330333304333053330633307333083330933310333113331233313333143331533316333173331833319333203332133322333233332433325333263332733328333293333033331333323333333334333353333633337333383333933340333413334233343333443334533346333473334833349333503335133352333533335433355333563335733358333593336033361333623336333364333653336633367333683336933370333713337233373333743337533376333773337833379333803338133382333833338433385333863338733388333893339033391333923339333394333953339633397333983339933400334013340233403334043340533406334073340833409334103341133412334133341433415334163341733418334193342033421334223342333424334253342633427334283342933430334313343233433334343343533436334373343833439334403344133442334433344433445334463344733448334493345033451334523345333454334553345633457334583345933460334613346233463334643346533466334673346833469334703347133472334733347433475334763347733478334793348033481334823348333484334853348633487334883348933490334913349233493334943349533496334973349833499335003350133502335033350433505335063350733508335093351033511335123351333514335153351633517335183351933520335213352233523335243352533526335273352833529335303353133532335333353433535335363353733538335393354033541335423354333544335453354633547335483354933550335513355233553335543355533556335573355833559335603356133562335633356433565335663356733568335693357033571335723357333574335753357633577335783357933580335813358233583335843358533586335873358833589335903359133592335933359433595335963359733598335993360033601336023360333604336053360633607336083360933610336113361233613336143361533616336173361833619336203362133622336233362433625336263362733628336293363033631336323363333634336353363633637336383363933640336413364233643336443364533646336473364833649336503365133652336533365433655336563365733658336593366033661336623366333664336653366633667336683366933670336713367233673336743367533676336773367833679336803368133682336833368433685336863368733688336893369033691336923369333694336953369633697336983369933700337013370233703337043370533706337073370833709337103371133712337133371433715337163371733718337193372033721337223372333724337253372633727337283372933730337313373233733337343373533736337373373833739337403374133742337433374433745337463374733748337493375033751337523375333754337553375633757337583375933760337613376233763337643376533766337673376833769337703377133772337733377433775337763377733778337793378033781337823378333784337853378633787337883378933790337913379233793337943379533796337973379833799338003380133802338033380433805338063380733808338093381033811338123381333814338153381633817338183381933820338213382233823338243382533826338273382833829338303383133832338333383433835338363383733838338393384033841338423384333844338453384633847338483384933850338513385233853338543385533856338573385833859338603386133862338633386433865338663386733868338693387033871338723387333874338753387633877338783387933880338813388233883338843388533886338873388833889338903389133892338933389433895338963389733898338993390033901339023390333904339053390633907339083390933910339113391233913339143391533916339173391833919339203392133922339233392433925339263392733928339293393033931339323393333934339353393633937339383393933940339413394233943339443394533946339473394833949339503395133952339533395433955339563395733958339593396033961339623396333964339653396633967339683396933970339713397233973339743397533976339773397833979339803398133982339833398433985339863398733988339893399033991339923399333994339953399633997339983399934000340013400234003340043400534006340073400834009340103401134012340133401434015340163401734018340193402034021340223402334024340253402634027340283402934030340313403234033340343403534036340373403834039340403404134042340433404434045340463404734048340493405034051340523405334054340553405634057340583405934060340613406234063340643406534066340673406834069340703407134072340733407434075340763407734078340793408034081340823408334084340853408634087340883408934090340913409234093340943409534096340973409834099341003410134102341033410434105341063410734108341093411034111341123411334114341153411634117341183411934120341213412234123341243412534126341273412834129341303413134132341333413434135341363413734138341393414034141341423414334144341453414634147341483414934150341513415234153341543415534156341573415834159341603416134162341633416434165341663416734168341693417034171341723417334174341753417634177341783417934180341813418234183341843418534186341873418834189341903419134192341933419434195341963419734198341993420034201342023420334204342053420634207342083420934210342113421234213342143421534216342173421834219342203422134222342233422434225342263422734228342293423034231342323423334234342353423634237342383423934240342413424234243342443424534246342473424834249342503425134252342533425434255342563425734258342593426034261342623426334264342653426634267342683426934270342713427234273342743427534276342773427834279342803428134282342833428434285342863428734288342893429034291342923429334294342953429634297342983429934300343013430234303343043430534306343073430834309343103431134312343133431434315343163431734318343193432034321343223432334324343253432634327343283432934330343313433234333343343433534336343373433834339343403434134342343433434434345343463434734348343493435034351343523435334354343553435634357343583435934360343613436234363343643436534366343673436834369343703437134372343733437434375343763437734378343793438034381343823438334384343853438634387343883438934390343913439234393343943439534396343973439834399344003440134402344033440434405344063440734408344093441034411344123441334414344153441634417344183441934420344213442234423344243442534426344273442834429344303443134432344333443434435344363443734438344393444034441344423444334444344453444634447344483444934450344513445234453344543445534456344573445834459344603446134462344633446434465344663446734468344693447034471344723447334474344753447634477344783447934480344813448234483344843448534486344873448834489344903449134492344933449434495344963449734498344993450034501345023450334504345053450634507345083450934510345113451234513345143451534516345173451834519345203452134522345233452434525345263452734528345293453034531345323453334534345353453634537345383453934540345413454234543345443454534546345473454834549345503455134552345533455434555345563455734558345593456034561345623456334564345653456634567345683456934570345713457234573345743457534576345773457834579345803458134582345833458434585345863458734588345893459034591345923459334594345953459634597345983459934600346013460234603346043460534606346073460834609346103461134612346133461434615346163461734618346193462034621346223462334624346253462634627346283462934630346313463234633346343463534636346373463834639346403464134642346433464434645346463464734648346493465034651346523465334654346553465634657346583465934660346613466234663346643466534666346673466834669346703467134672346733467434675346763467734678346793468034681346823468334684346853468634687346883468934690346913469234693346943469534696346973469834699347003470134702347033470434705347063470734708347093471034711347123471334714347153471634717347183471934720347213472234723347243472534726347273472834729347303473134732347333473434735347363473734738347393474034741347423474334744347453474634747347483474934750347513475234753347543475534756347573475834759347603476134762347633476434765347663476734768347693477034771347723477334774347753477634777347783477934780347813478234783347843478534786347873478834789347903479134792347933479434795347963479734798347993480034801348023480334804348053480634807348083480934810348113481234813348143481534816348173481834819348203482134822348233482434825348263482734828348293483034831348323483334834348353483634837348383483934840348413484234843348443484534846348473484834849348503485134852348533485434855348563485734858348593486034861348623486334864348653486634867348683486934870348713487234873348743487534876348773487834879348803488134882348833488434885348863488734888348893489034891348923489334894348953489634897348983489934900349013490234903349043490534906349073490834909349103491134912349133491434915349163491734918349193492034921349223492334924349253492634927349283492934930349313493234933349343493534936349373493834939349403494134942349433494434945349463494734948349493495034951349523495334954349553495634957349583495934960349613496234963349643496534966349673496834969349703497134972349733497434975349763497734978349793498034981349823498334984349853498634987349883498934990349913499234993349943499534996349973499834999350003500135002350033500435005350063500735008350093501035011350123501335014350153501635017350183501935020350213502235023350243502535026350273502835029350303503135032350333503435035350363503735038350393504035041350423504335044350453504635047350483504935050350513505235053350543505535056350573505835059350603506135062350633506435065350663506735068350693507035071350723507335074350753507635077350783507935080350813508235083350843508535086350873508835089350903509135092350933509435095350963509735098350993510035101351023510335104351053510635107351083510935110351113511235113351143511535116351173511835119351203512135122351233512435125351263512735128351293513035131351323513335134351353513635137351383513935140351413514235143351443514535146351473514835149351503515135152351533515435155351563515735158351593516035161351623516335164351653516635167351683516935170351713517235173351743517535176351773517835179351803518135182351833518435185351863518735188351893519035191351923519335194351953519635197351983519935200352013520235203352043520535206352073520835209352103521135212352133521435215352163521735218352193522035221352223522335224352253522635227352283522935230352313523235233352343523535236352373523835239352403524135242352433524435245352463524735248352493525035251352523525335254352553525635257352583525935260352613526235263352643526535266352673526835269352703527135272352733527435275352763527735278352793528035281352823528335284352853528635287352883528935290352913529235293352943529535296352973529835299353003530135302353033530435305353063530735308353093531035311353123531335314353153531635317353183531935320353213532235323353243532535326353273532835329353303533135332353333533435335353363533735338353393534035341353423534335344353453534635347353483534935350353513535235353353543535535356353573535835359353603536135362353633536435365353663536735368353693537035371353723537335374353753537635377353783537935380353813538235383353843538535386353873538835389353903539135392353933539435395353963539735398353993540035401354023540335404354053540635407354083540935410354113541235413354143541535416354173541835419354203542135422354233542435425354263542735428354293543035431354323543335434354353543635437354383543935440354413544235443354443544535446354473544835449354503545135452354533545435455354563545735458354593546035461354623546335464354653546635467354683546935470354713547235473354743547535476354773547835479354803548135482354833548435485354863548735488354893549035491354923549335494354953549635497354983549935500355013550235503355043550535506355073550835509355103551135512355133551435515355163551735518355193552035521355223552335524355253552635527355283552935530355313553235533355343553535536355373553835539355403554135542355433554435545355463554735548355493555035551355523555335554355553555635557355583555935560355613556235563355643556535566355673556835569355703557135572355733557435575355763557735578355793558035581355823558335584355853558635587355883558935590355913559235593355943559535596355973559835599356003560135602356033560435605356063560735608356093561035611356123561335614356153561635617356183561935620356213562235623356243562535626356273562835629356303563135632356333563435635356363563735638356393564035641356423564335644356453564635647356483564935650356513565235653356543565535656356573565835659356603566135662356633566435665356663566735668356693567035671356723567335674356753567635677356783567935680356813568235683356843568535686356873568835689356903569135692356933569435695356963569735698356993570035701357023570335704357053570635707357083570935710357113571235713357143571535716357173571835719357203572135722357233572435725357263572735728357293573035731357323573335734357353573635737357383573935740357413574235743357443574535746357473574835749357503575135752357533575435755357563575735758357593576035761357623576335764357653576635767357683576935770357713577235773357743577535776357773577835779357803578135782357833578435785357863578735788357893579035791357923579335794357953579635797357983579935800358013580235803358043580535806358073580835809358103581135812358133581435815358163581735818358193582035821358223582335824358253582635827358283582935830358313583235833358343583535836358373583835839358403584135842358433584435845358463584735848358493585035851358523585335854358553585635857358583585935860358613586235863358643586535866358673586835869358703587135872358733587435875358763587735878358793588035881358823588335884358853588635887358883588935890358913589235893358943589535896358973589835899359003590135902359033590435905359063590735908359093591035911359123591335914359153591635917359183591935920359213592235923359243592535926359273592835929359303593135932359333593435935359363593735938359393594035941359423594335944359453594635947359483594935950359513595235953359543595535956359573595835959359603596135962359633596435965359663596735968359693597035971359723597335974359753597635977359783597935980359813598235983359843598535986359873598835989359903599135992359933599435995359963599735998359993600036001360023600336004360053600636007360083600936010360113601236013360143601536016360173601836019360203602136022360233602436025360263602736028360293603036031360323603336034360353603636037360383603936040360413604236043360443604536046360473604836049360503605136052360533605436055360563605736058360593606036061360623606336064360653606636067360683606936070360713607236073360743607536076360773607836079360803608136082360833608436085360863608736088360893609036091360923609336094360953609636097360983609936100361013610236103361043610536106361073610836109361103611136112361133611436115361163611736118361193612036121361223612336124361253612636127361283612936130361313613236133361343613536136361373613836139361403614136142361433614436145361463614736148361493615036151361523615336154361553615636157361583615936160361613616236163361643616536166361673616836169361703617136172361733617436175361763617736178361793618036181361823618336184361853618636187361883618936190361913619236193361943619536196361973619836199362003620136202362033620436205362063620736208362093621036211362123621336214362153621636217362183621936220362213622236223362243622536226362273622836229362303623136232362333623436235362363623736238362393624036241362423624336244362453624636247362483624936250362513625236253362543625536256362573625836259362603626136262362633626436265362663626736268362693627036271362723627336274362753627636277362783627936280362813628236283362843628536286362873628836289362903629136292362933629436295362963629736298362993630036301363023630336304363053630636307363083630936310363113631236313363143631536316363173631836319363203632136322363233632436325363263632736328363293633036331363323633336334363353633636337363383633936340363413634236343363443634536346363473634836349363503635136352363533635436355363563635736358363593636036361363623636336364363653636636367363683636936370363713637236373363743637536376363773637836379363803638136382363833638436385363863638736388363893639036391363923639336394363953639636397363983639936400364013640236403364043640536406364073640836409364103641136412364133641436415364163641736418364193642036421364223642336424364253642636427364283642936430364313643236433364343643536436364373643836439364403644136442364433644436445364463644736448364493645036451364523645336454364553645636457364583645936460364613646236463364643646536466364673646836469364703647136472364733647436475364763647736478364793648036481364823648336484364853648636487364883648936490364913649236493364943649536496364973649836499365003650136502365033650436505365063650736508365093651036511365123651336514365153651636517365183651936520365213652236523365243652536526365273652836529365303653136532365333653436535365363653736538365393654036541365423654336544365453654636547365483654936550365513655236553365543655536556365573655836559365603656136562365633656436565365663656736568365693657036571365723657336574365753657636577365783657936580365813658236583365843658536586365873658836589365903659136592365933659436595365963659736598365993660036601366023660336604366053660636607366083660936610366113661236613366143661536616366173661836619366203662136622366233662436625366263662736628366293663036631366323663336634366353663636637366383663936640366413664236643366443664536646366473664836649366503665136652366533665436655366563665736658366593666036661366623666336664366653666636667366683666936670366713667236673366743667536676366773667836679366803668136682366833668436685366863668736688366893669036691366923669336694366953669636697366983669936700367013670236703367043670536706367073670836709367103671136712367133671436715367163671736718367193672036721367223672336724367253672636727367283672936730367313673236733367343673536736367373673836739367403674136742367433674436745367463674736748367493675036751367523675336754367553675636757367583675936760367613676236763367643676536766367673676836769367703677136772367733677436775367763677736778367793678036781367823678336784367853678636787367883678936790367913679236793367943679536796367973679836799368003680136802368033680436805368063680736808368093681036811368123681336814368153681636817368183681936820368213682236823368243682536826368273682836829368303683136832368333683436835368363683736838368393684036841368423684336844368453684636847368483684936850368513685236853368543685536856368573685836859368603686136862368633686436865368663686736868368693687036871368723687336874368753687636877368783687936880368813688236883368843688536886368873688836889368903689136892368933689436895368963689736898368993690036901369023690336904369053690636907369083690936910369113691236913369143691536916369173691836919369203692136922369233692436925369263692736928369293693036931369323693336934369353693636937369383693936940369413694236943369443694536946369473694836949369503695136952369533695436955369563695736958369593696036961369623696336964369653696636967369683696936970369713697236973369743697536976369773697836979369803698136982369833698436985369863698736988369893699036991369923699336994369953699636997369983699937000370013700237003370043700537006370073700837009370103701137012370133701437015370163701737018370193702037021370223702337024370253702637027370283702937030370313703237033370343703537036370373703837039370403704137042370433704437045370463704737048370493705037051370523705337054370553705637057370583705937060370613706237063370643706537066370673706837069370703707137072370733707437075370763707737078370793708037081370823708337084370853708637087370883708937090370913709237093370943709537096370973709837099371003710137102371033710437105371063710737108371093711037111371123711337114371153711637117371183711937120371213712237123371243712537126371273712837129371303713137132371333713437135371363713737138371393714037141371423714337144371453714637147371483714937150371513715237153371543715537156371573715837159371603716137162371633716437165371663716737168371693717037171371723717337174371753717637177371783717937180371813718237183371843718537186371873718837189371903719137192371933719437195371963719737198371993720037201372023720337204372053720637207372083720937210372113721237213372143721537216372173721837219372203722137222372233722437225372263722737228372293723037231372323723337234372353723637237372383723937240372413724237243372443724537246372473724837249372503725137252372533725437255372563725737258372593726037261372623726337264372653726637267372683726937270372713727237273372743727537276372773727837279372803728137282372833728437285372863728737288372893729037291372923729337294372953729637297372983729937300373013730237303373043730537306373073730837309373103731137312373133731437315373163731737318373193732037321373223732337324373253732637327373283732937330373313733237333373343733537336373373733837339373403734137342373433734437345373463734737348373493735037351373523735337354373553735637357373583735937360373613736237363373643736537366373673736837369373703737137372373733737437375373763737737378373793738037381373823738337384373853738637387373883738937390373913739237393373943739537396373973739837399374003740137402374033740437405374063740737408374093741037411374123741337414374153741637417374183741937420374213742237423374243742537426374273742837429374303743137432374333743437435374363743737438374393744037441374423744337444374453744637447374483744937450374513745237453374543745537456374573745837459374603746137462374633746437465374663746737468374693747037471374723747337474374753747637477374783747937480374813748237483374843748537486374873748837489374903749137492374933749437495374963749737498374993750037501375023750337504375053750637507375083750937510375113751237513375143751537516375173751837519375203752137522375233752437525375263752737528375293753037531375323753337534375353753637537375383753937540375413754237543375443754537546375473754837549375503755137552375533755437555375563755737558375593756037561375623756337564375653756637567375683756937570375713757237573375743757537576375773757837579375803758137582375833758437585375863758737588375893759037591375923759337594375953759637597375983759937600376013760237603376043760537606376073760837609376103761137612376133761437615376163761737618376193762037621376223762337624376253762637627376283762937630376313763237633376343763537636376373763837639376403764137642376433764437645376463764737648376493765037651376523765337654376553765637657376583765937660376613766237663376643766537666376673766837669376703767137672376733767437675376763767737678376793768037681376823768337684376853768637687376883768937690376913769237693376943769537696376973769837699377003770137702377033770437705377063770737708377093771037711377123771337714377153771637717377183771937720377213772237723377243772537726377273772837729377303773137732377333773437735377363773737738377393774037741377423774337744377453774637747377483774937750377513775237753377543775537756377573775837759377603776137762377633776437765377663776737768377693777037771377723777337774377753777637777377783777937780377813778237783377843778537786377873778837789377903779137792377933779437795377963779737798377993780037801378023780337804378053780637807378083780937810378113781237813378143781537816378173781837819378203782137822378233782437825378263782737828378293783037831378323783337834378353783637837378383783937840378413784237843378443784537846378473784837849378503785137852378533785437855378563785737858378593786037861378623786337864378653786637867378683786937870378713787237873378743787537876378773787837879378803788137882378833788437885378863788737888378893789037891378923789337894378953789637897378983789937900379013790237903379043790537906379073790837909379103791137912379133791437915379163791737918379193792037921379223792337924379253792637927379283792937930379313793237933379343793537936379373793837939379403794137942379433794437945379463794737948379493795037951379523795337954379553795637957379583795937960379613796237963379643796537966379673796837969379703797137972379733797437975379763797737978379793798037981379823798337984379853798637987379883798937990379913799237993379943799537996379973799837999380003800138002380033800438005380063800738008380093801038011380123801338014380153801638017380183801938020380213802238023380243802538026380273802838029380303803138032380333803438035380363803738038380393804038041380423804338044380453804638047380483804938050380513805238053380543805538056380573805838059380603806138062380633806438065380663806738068380693807038071380723807338074380753807638077380783807938080380813808238083380843808538086380873808838089380903809138092380933809438095380963809738098380993810038101381023810338104381053810638107381083810938110381113811238113381143811538116381173811838119381203812138122381233812438125381263812738128381293813038131381323813338134381353813638137381383813938140381413814238143381443814538146381473814838149381503815138152381533815438155381563815738158381593816038161381623816338164381653816638167381683816938170381713817238173381743817538176381773817838179381803818138182381833818438185381863818738188381893819038191381923819338194381953819638197381983819938200382013820238203382043820538206382073820838209382103821138212382133821438215382163821738218382193822038221382223822338224382253822638227382283822938230382313823238233382343823538236382373823838239382403824138242382433824438245382463824738248382493825038251382523825338254382553825638257382583825938260382613826238263382643826538266382673826838269382703827138272382733827438275382763827738278382793828038281382823828338284382853828638287382883828938290382913829238293382943829538296382973829838299383003830138302383033830438305383063830738308383093831038311383123831338314383153831638317383183831938320383213832238323383243832538326383273832838329383303833138332383333833438335383363833738338383393834038341383423834338344383453834638347383483834938350383513835238353383543835538356383573835838359383603836138362383633836438365383663836738368383693837038371383723837338374383753837638377383783837938380383813838238383383843838538386383873838838389383903839138392383933839438395383963839738398383993840038401384023840338404384053840638407384083840938410384113841238413384143841538416384173841838419384203842138422384233842438425384263842738428384293843038431384323843338434384353843638437384383843938440384413844238443384443844538446384473844838449384503845138452384533845438455384563845738458384593846038461384623846338464384653846638467384683846938470384713847238473384743847538476384773847838479384803848138482384833848438485384863848738488384893849038491384923849338494384953849638497384983849938500385013850238503385043850538506385073850838509385103851138512385133851438515385163851738518385193852038521385223852338524385253852638527385283852938530385313853238533385343853538536385373853838539385403854138542385433854438545385463854738548385493855038551385523855338554385553855638557385583855938560385613856238563385643856538566385673856838569385703857138572385733857438575385763857738578385793858038581385823858338584385853858638587385883858938590385913859238593385943859538596385973859838599386003860138602386033860438605386063860738608386093861038611386123861338614386153861638617386183861938620386213862238623386243862538626386273862838629386303863138632386333863438635386363863738638386393864038641386423864338644386453864638647386483864938650386513865238653386543865538656386573865838659386603866138662386633866438665386663866738668386693867038671386723867338674386753867638677386783867938680386813868238683386843868538686386873868838689386903869138692386933869438695386963869738698386993870038701387023870338704387053870638707387083870938710387113871238713387143871538716387173871838719387203872138722387233872438725387263872738728387293873038731387323873338734387353873638737387383873938740387413874238743387443874538746387473874838749387503875138752387533875438755387563875738758387593876038761387623876338764387653876638767387683876938770387713877238773387743877538776387773877838779387803878138782387833878438785387863878738788387893879038791387923879338794387953879638797387983879938800388013880238803388043880538806388073880838809388103881138812388133881438815388163881738818388193882038821388223882338824388253882638827388283882938830388313883238833388343883538836388373883838839388403884138842388433884438845388463884738848388493885038851388523885338854388553885638857388583885938860388613886238863388643886538866388673886838869388703887138872388733887438875388763887738878388793888038881388823888338884388853888638887388883888938890388913889238893388943889538896388973889838899389003890138902389033890438905389063890738908389093891038911389123891338914389153891638917389183891938920389213892238923389243892538926389273892838929389303893138932389333893438935389363893738938389393894038941389423894338944389453894638947389483894938950389513895238953389543895538956389573895838959389603896138962389633896438965389663896738968389693897038971389723897338974389753897638977389783897938980389813898238983389843898538986389873898838989389903899138992389933899438995389963899738998389993900039001390023900339004390053900639007390083900939010390113901239013390143901539016390173901839019390203902139022390233902439025390263902739028390293903039031390323903339034390353903639037390383903939040390413904239043390443904539046390473904839049390503905139052390533905439055390563905739058390593906039061390623906339064390653906639067390683906939070390713907239073390743907539076390773907839079390803908139082390833908439085390863908739088390893909039091390923909339094390953909639097390983909939100391013910239103391043910539106391073910839109391103911139112391133911439115391163911739118391193912039121391223912339124391253912639127391283912939130391313913239133391343913539136391373913839139391403914139142391433914439145391463914739148391493915039151391523915339154391553915639157391583915939160391613916239163391643916539166391673916839169391703917139172391733917439175391763917739178391793918039181391823918339184391853918639187391883918939190391913919239193391943919539196391973919839199392003920139202392033920439205392063920739208392093921039211392123921339214392153921639217392183921939220392213922239223392243922539226392273922839229392303923139232392333923439235392363923739238392393924039241392423924339244392453924639247392483924939250392513925239253392543925539256392573925839259392603926139262392633926439265392663926739268392693927039271392723927339274392753927639277392783927939280392813928239283392843928539286392873928839289392903929139292392933929439295392963929739298392993930039301393023930339304393053930639307393083930939310393113931239313393143931539316393173931839319393203932139322393233932439325393263932739328393293933039331393323933339334393353933639337393383933939340393413934239343393443934539346393473934839349393503935139352393533935439355393563935739358393593936039361393623936339364393653936639367393683936939370393713937239373393743937539376393773937839379393803938139382393833938439385393863938739388393893939039391393923939339394393953939639397393983939939400394013940239403394043940539406394073940839409394103941139412394133941439415394163941739418394193942039421394223942339424394253942639427394283942939430394313943239433394343943539436394373943839439394403944139442394433944439445394463944739448394493945039451394523945339454394553945639457394583945939460394613946239463394643946539466394673946839469394703947139472394733947439475394763947739478394793948039481394823948339484394853948639487394883948939490394913949239493394943949539496394973949839499395003950139502395033950439505395063950739508395093951039511395123951339514395153951639517395183951939520395213952239523395243952539526395273952839529395303953139532395333953439535395363953739538395393954039541395423954339544395453954639547395483954939550395513955239553395543955539556395573955839559395603956139562395633956439565395663956739568395693957039571395723957339574395753957639577395783957939580395813958239583395843958539586395873958839589395903959139592395933959439595395963959739598395993960039601396023960339604396053960639607396083960939610396113961239613396143961539616396173961839619396203962139622396233962439625396263962739628396293963039631396323963339634396353963639637396383963939640396413964239643396443964539646396473964839649396503965139652396533965439655396563965739658396593966039661396623966339664396653966639667396683966939670396713967239673396743967539676396773967839679396803968139682396833968439685396863968739688396893969039691396923969339694396953969639697396983969939700397013970239703397043970539706397073970839709397103971139712397133971439715397163971739718397193972039721397223972339724397253972639727397283972939730397313973239733397343973539736397373973839739397403974139742397433974439745397463974739748397493975039751397523975339754397553975639757397583975939760397613976239763397643976539766397673976839769397703977139772397733977439775397763977739778397793978039781397823978339784397853978639787397883978939790397913979239793397943979539796397973979839799398003980139802398033980439805398063980739808398093981039811398123981339814398153981639817398183981939820398213982239823398243982539826398273982839829398303983139832398333983439835398363983739838398393984039841398423984339844398453984639847398483984939850398513985239853398543985539856398573985839859398603986139862398633986439865398663986739868398693987039871398723987339874398753987639877398783987939880398813988239883398843988539886398873988839889398903989139892398933989439895398963989739898398993990039901399023990339904399053990639907399083990939910399113991239913399143991539916399173991839919399203992139922399233992439925399263992739928399293993039931399323993339934399353993639937399383993939940399413994239943399443994539946399473994839949399503995139952399533995439955399563995739958399593996039961399623996339964399653996639967399683996939970399713997239973399743997539976399773997839979399803998139982399833998439985399863998739988399893999039991399923999339994399953999639997399983999940000400014000240003400044000540006400074000840009400104001140012400134001440015400164001740018400194002040021400224002340024400254002640027400284002940030400314003240033400344003540036400374003840039400404004140042400434004440045400464004740048400494005040051400524005340054400554005640057400584005940060400614006240063400644006540066400674006840069400704007140072400734007440075400764007740078400794008040081400824008340084400854008640087400884008940090400914009240093400944009540096400974009840099401004010140102401034010440105401064010740108401094011040111401124011340114401154011640117401184011940120401214012240123401244012540126401274012840129401304013140132401334013440135401364013740138401394014040141401424014340144401454014640147401484014940150401514015240153401544015540156401574015840159401604016140162401634016440165401664016740168401694017040171401724017340174401754017640177401784017940180401814018240183401844018540186401874018840189401904019140192401934019440195401964019740198401994020040201402024020340204402054020640207402084020940210402114021240213402144021540216402174021840219402204022140222402234022440225402264022740228402294023040231402324023340234402354023640237402384023940240402414024240243402444024540246402474024840249402504025140252402534025440255402564025740258402594026040261402624026340264402654026640267402684026940270402714027240273402744027540276402774027840279402804028140282402834028440285402864028740288402894029040291402924029340294402954029640297402984029940300403014030240303403044030540306403074030840309403104031140312403134031440315403164031740318403194032040321403224032340324403254032640327403284032940330403314033240333403344033540336403374033840339403404034140342403434034440345403464034740348403494035040351403524035340354403554035640357403584035940360403614036240363403644036540366403674036840369403704037140372403734037440375403764037740378403794038040381403824038340384403854038640387403884038940390403914039240393403944039540396403974039840399404004040140402404034040440405404064040740408404094041040411404124041340414404154041640417404184041940420404214042240423404244042540426404274042840429404304043140432404334043440435404364043740438404394044040441404424044340444404454044640447404484044940450404514045240453404544045540456404574045840459404604046140462404634046440465404664046740468404694047040471404724047340474404754047640477404784047940480404814048240483404844048540486404874048840489404904049140492404934049440495404964049740498404994050040501405024050340504405054050640507405084050940510405114051240513405144051540516405174051840519405204052140522405234052440525405264052740528405294053040531405324053340534405354053640537405384053940540405414054240543405444054540546405474054840549405504055140552405534055440555405564055740558405594056040561405624056340564405654056640567405684056940570405714057240573405744057540576405774057840579405804058140582405834058440585405864058740588405894059040591405924059340594405954059640597405984059940600406014060240603406044060540606406074060840609406104061140612406134061440615406164061740618406194062040621406224062340624406254062640627406284062940630406314063240633406344063540636406374063840639406404064140642406434064440645406464064740648406494065040651406524065340654406554065640657406584065940660406614066240663406644066540666406674066840669406704067140672406734067440675406764067740678406794068040681406824068340684406854068640687406884068940690406914069240693406944069540696406974069840699407004070140702407034070440705407064070740708407094071040711407124071340714407154071640717407184071940720407214072240723407244072540726407274072840729407304073140732407334073440735407364073740738407394074040741407424074340744407454074640747407484074940750407514075240753407544075540756407574075840759407604076140762407634076440765407664076740768407694077040771407724077340774407754077640777407784077940780407814078240783407844078540786407874078840789407904079140792407934079440795407964079740798407994080040801408024080340804408054080640807408084080940810408114081240813408144081540816408174081840819408204082140822408234082440825408264082740828408294083040831408324083340834408354083640837408384083940840408414084240843408444084540846408474084840849408504085140852408534085440855408564085740858408594086040861408624086340864408654086640867408684086940870408714087240873408744087540876408774087840879408804088140882408834088440885408864088740888408894089040891408924089340894408954089640897408984089940900409014090240903409044090540906409074090840909409104091140912409134091440915409164091740918409194092040921409224092340924409254092640927409284092940930409314093240933409344093540936409374093840939409404094140942409434094440945409464094740948409494095040951409524095340954409554095640957409584095940960409614096240963409644096540966409674096840969409704097140972409734097440975409764097740978409794098040981409824098340984409854098640987409884098940990409914099240993409944099540996409974099840999410004100141002410034100441005410064100741008410094101041011410124101341014410154101641017410184101941020410214102241023410244102541026410274102841029410304103141032410334103441035410364103741038410394104041041410424104341044410454104641047410484104941050410514105241053410544105541056410574105841059410604106141062410634106441065410664106741068410694107041071410724107341074410754107641077410784107941080410814108241083410844108541086410874108841089410904109141092410934109441095410964109741098410994110041101411024110341104411054110641107411084110941110411114111241113411144111541116411174111841119411204112141122411234112441125411264112741128411294113041131411324113341134411354113641137411384113941140411414114241143411444114541146411474114841149411504115141152411534115441155411564115741158411594116041161411624116341164411654116641167411684116941170411714117241173411744117541176411774117841179411804118141182411834118441185411864118741188411894119041191411924119341194411954119641197411984119941200412014120241203412044120541206412074120841209412104121141212412134121441215412164121741218412194122041221412224122341224412254122641227412284122941230412314123241233412344123541236412374123841239412404124141242412434124441245412464124741248412494125041251412524125341254412554125641257412584125941260412614126241263412644126541266412674126841269412704127141272412734127441275412764127741278412794128041281412824128341284412854128641287412884128941290412914129241293412944129541296412974129841299413004130141302413034130441305413064130741308413094131041311413124131341314413154131641317413184131941320413214132241323413244132541326413274132841329413304133141332413334133441335413364133741338413394134041341413424134341344413454134641347413484134941350413514135241353413544135541356413574135841359413604136141362413634136441365413664136741368413694137041371413724137341374413754137641377413784137941380413814138241383413844138541386413874138841389413904139141392413934139441395413964139741398413994140041401414024140341404414054140641407414084140941410414114141241413414144141541416414174141841419414204142141422414234142441425414264142741428414294143041431414324143341434414354143641437414384143941440414414144241443414444144541446414474144841449414504145141452414534145441455414564145741458414594146041461414624146341464414654146641467414684146941470414714147241473414744147541476414774147841479414804148141482414834148441485414864148741488414894149041491414924149341494414954149641497414984149941500415014150241503415044150541506415074150841509415104151141512415134151441515415164151741518415194152041521415224152341524415254152641527415284152941530415314153241533415344153541536415374153841539415404154141542415434154441545415464154741548415494155041551415524155341554415554155641557415584155941560415614156241563415644156541566415674156841569415704157141572415734157441575415764157741578415794158041581415824158341584415854158641587415884158941590415914159241593415944159541596415974159841599416004160141602416034160441605416064160741608416094161041611416124161341614416154161641617416184161941620416214162241623416244162541626416274162841629416304163141632416334163441635416364163741638416394164041641416424164341644416454164641647416484164941650416514165241653416544165541656416574165841659416604166141662416634166441665416664166741668416694167041671416724167341674416754167641677416784167941680416814168241683416844168541686416874168841689416904169141692416934169441695416964169741698416994170041701417024170341704417054170641707417084170941710417114171241713417144171541716417174171841719417204172141722417234172441725417264172741728417294173041731417324173341734417354173641737417384173941740417414174241743417444174541746417474174841749417504175141752417534175441755417564175741758417594176041761417624176341764417654176641767417684176941770417714177241773417744177541776417774177841779417804178141782417834178441785417864178741788417894179041791417924179341794417954179641797417984179941800418014180241803418044180541806418074180841809418104181141812418134181441815418164181741818418194182041821418224182341824418254182641827418284182941830418314183241833418344183541836418374183841839418404184141842418434184441845418464184741848418494185041851418524185341854418554185641857418584185941860418614186241863418644186541866418674186841869418704187141872418734187441875418764187741878418794188041881418824188341884418854188641887418884188941890418914189241893418944189541896418974189841899419004190141902419034190441905419064190741908419094191041911419124191341914419154191641917419184191941920419214192241923419244192541926419274192841929419304193141932419334193441935419364193741938419394194041941419424194341944419454194641947419484194941950419514195241953419544195541956419574195841959419604196141962419634196441965419664196741968419694197041971419724197341974419754197641977419784197941980419814198241983419844198541986419874198841989419904199141992419934199441995419964199741998419994200042001420024200342004420054200642007420084200942010420114201242013420144201542016420174201842019420204202142022420234202442025420264202742028420294203042031420324203342034420354203642037420384203942040420414204242043420444204542046420474204842049420504205142052420534205442055420564205742058420594206042061420624206342064420654206642067420684206942070420714207242073420744207542076420774207842079420804208142082420834208442085420864208742088420894209042091420924209342094420954209642097420984209942100421014210242103421044210542106421074210842109421104211142112421134211442115421164211742118421194212042121421224212342124421254212642127421284212942130421314213242133421344213542136421374213842139421404214142142421434214442145421464214742148421494215042151421524215342154421554215642157421584215942160421614216242163421644216542166421674216842169421704217142172421734217442175421764217742178421794218042181421824218342184421854218642187421884218942190421914219242193421944219542196421974219842199422004220142202422034220442205422064220742208422094221042211422124221342214422154221642217422184221942220422214222242223422244222542226422274222842229422304223142232422334223442235422364223742238422394224042241422424224342244422454224642247422484224942250422514225242253422544225542256422574225842259422604226142262422634226442265422664226742268422694227042271422724227342274422754227642277422784227942280422814228242283422844228542286422874228842289422904229142292422934229442295422964229742298422994230042301423024230342304423054230642307423084230942310423114231242313423144231542316423174231842319423204232142322423234232442325423264232742328423294233042331423324233342334423354233642337423384233942340423414234242343423444234542346423474234842349423504235142352423534235442355423564235742358423594236042361423624236342364423654236642367423684236942370423714237242373423744237542376423774237842379423804238142382423834238442385423864238742388423894239042391423924239342394423954239642397423984239942400424014240242403424044240542406424074240842409424104241142412424134241442415424164241742418424194242042421424224242342424424254242642427424284242942430424314243242433424344243542436424374243842439424404244142442424434244442445424464244742448424494245042451424524245342454424554245642457424584245942460424614246242463424644246542466424674246842469424704247142472424734247442475424764247742478424794248042481424824248342484424854248642487424884248942490424914249242493424944249542496424974249842499425004250142502425034250442505425064250742508425094251042511425124251342514425154251642517425184251942520425214252242523425244252542526425274252842529425304253142532425334253442535425364253742538425394254042541425424254342544425454254642547425484254942550425514255242553425544255542556425574255842559425604256142562425634256442565425664256742568425694257042571425724257342574425754257642577425784257942580425814258242583425844258542586425874258842589425904259142592425934259442595425964259742598425994260042601426024260342604426054260642607426084260942610426114261242613426144261542616426174261842619426204262142622426234262442625426264262742628426294263042631426324263342634426354263642637426384263942640426414264242643426444264542646426474264842649426504265142652426534265442655426564265742658426594266042661426624266342664426654266642667426684266942670426714267242673426744267542676426774267842679426804268142682426834268442685426864268742688426894269042691426924269342694426954269642697426984269942700427014270242703427044270542706427074270842709427104271142712427134271442715427164271742718427194272042721427224272342724427254272642727427284272942730427314273242733427344273542736427374273842739427404274142742427434274442745427464274742748427494275042751427524275342754427554275642757427584275942760427614276242763427644276542766427674276842769427704277142772427734277442775427764277742778427794278042781427824278342784427854278642787427884278942790427914279242793427944279542796427974279842799428004280142802428034280442805428064280742808428094281042811428124281342814428154281642817428184281942820428214282242823428244282542826428274282842829428304283142832428334283442835428364283742838428394284042841428424284342844428454284642847428484284942850428514285242853428544285542856428574285842859428604286142862428634286442865428664286742868428694287042871428724287342874428754287642877428784287942880428814288242883428844288542886428874288842889428904289142892428934289442895428964289742898428994290042901429024290342904429054290642907429084290942910429114291242913429144291542916429174291842919429204292142922429234292442925429264292742928429294293042931429324293342934429354293642937429384293942940429414294242943429444294542946429474294842949429504295142952429534295442955429564295742958429594296042961429624296342964429654296642967429684296942970429714297242973429744297542976429774297842979429804298142982429834298442985429864298742988429894299042991429924299342994429954299642997429984299943000430014300243003430044300543006430074300843009430104301143012430134301443015430164301743018430194302043021430224302343024430254302643027430284302943030430314303243033430344303543036430374303843039430404304143042430434304443045430464304743048430494305043051430524305343054430554305643057430584305943060430614306243063430644306543066430674306843069430704307143072430734307443075430764307743078430794308043081430824308343084430854308643087430884308943090430914309243093430944309543096430974309843099431004310143102431034310443105431064310743108431094311043111431124311343114431154311643117431184311943120431214312243123431244312543126431274312843129431304313143132431334313443135431364313743138431394314043141431424314343144431454314643147431484314943150431514315243153431544315543156431574315843159431604316143162431634316443165431664316743168431694317043171431724317343174431754317643177431784317943180431814318243183431844318543186431874318843189431904319143192431934319443195431964319743198431994320043201432024320343204432054320643207432084320943210432114321243213432144321543216432174321843219432204322143222432234322443225432264322743228432294323043231432324323343234432354323643237432384323943240432414324243243432444324543246432474324843249432504325143252432534325443255432564325743258432594326043261432624326343264432654326643267432684326943270432714327243273432744327543276432774327843279432804328143282432834328443285432864328743288432894329043291432924329343294432954329643297432984329943300433014330243303433044330543306433074330843309433104331143312433134331443315433164331743318433194332043321433224332343324433254332643327433284332943330433314333243333433344333543336433374333843339433404334143342433434334443345433464334743348433494335043351433524335343354433554335643357433584335943360433614336243363433644336543366433674336843369433704337143372433734337443375433764337743378433794338043381433824338343384433854338643387433884338943390433914339243393433944339543396433974339843399434004340143402434034340443405434064340743408434094341043411434124341343414434154341643417434184341943420434214342243423434244342543426434274342843429434304343143432434334343443435434364343743438434394344043441434424344343444434454344643447434484344943450434514345243453434544345543456434574345843459434604346143462434634346443465434664346743468434694347043471434724347343474434754347643477434784347943480434814348243483434844348543486434874348843489434904349143492434934349443495434964349743498434994350043501435024350343504435054350643507435084350943510435114351243513435144351543516435174351843519435204352143522435234352443525435264352743528435294353043531435324353343534435354353643537435384353943540435414354243543435444354543546435474354843549435504355143552435534355443555435564355743558435594356043561435624356343564435654356643567435684356943570435714357243573435744357543576435774357843579435804358143582435834358443585435864358743588435894359043591435924359343594435954359643597435984359943600436014360243603436044360543606436074360843609436104361143612436134361443615436164361743618436194362043621436224362343624436254362643627436284362943630436314363243633436344363543636436374363843639436404364143642436434364443645436464364743648436494365043651436524365343654436554365643657436584365943660436614366243663436644366543666436674366843669436704367143672436734367443675436764367743678436794368043681436824368343684436854368643687436884368943690436914369243693436944369543696436974369843699437004370143702437034370443705437064370743708437094371043711437124371343714437154371643717437184371943720437214372243723437244372543726437274372843729437304373143732437334373443735437364373743738437394374043741437424374343744437454374643747437484374943750437514375243753437544375543756437574375843759437604376143762437634376443765437664376743768437694377043771437724377343774437754377643777437784377943780437814378243783437844378543786437874378843789437904379143792437934379443795437964379743798437994380043801438024380343804438054380643807438084380943810438114381243813438144381543816438174381843819438204382143822438234382443825438264382743828438294383043831438324383343834438354383643837438384383943840438414384243843438444384543846438474384843849438504385143852438534385443855438564385743858438594386043861438624386343864438654386643867438684386943870438714387243873438744387543876438774387843879438804388143882438834388443885438864388743888438894389043891438924389343894438954389643897438984389943900439014390243903439044390543906439074390843909439104391143912439134391443915439164391743918439194392043921439224392343924439254392643927439284392943930439314393243933439344393543936439374393843939439404394143942439434394443945439464394743948439494395043951439524395343954439554395643957439584395943960439614396243963439644396543966439674396843969439704397143972439734397443975439764397743978439794398043981439824398343984439854398643987439884398943990439914399243993439944399543996439974399843999440004400144002440034400444005440064400744008440094401044011440124401344014440154401644017440184401944020440214402244023440244402544026440274402844029440304403144032440334403444035440364403744038440394404044041440424404344044440454404644047440484404944050440514405244053440544405544056440574405844059440604406144062440634406444065440664406744068440694407044071440724407344074440754407644077440784407944080440814408244083440844408544086440874408844089440904409144092440934409444095440964409744098440994410044101441024410344104441054410644107441084410944110441114411244113441144411544116441174411844119441204412144122441234412444125441264412744128441294413044131441324413344134441354413644137441384413944140441414414244143441444414544146441474414844149441504415144152441534415444155441564415744158441594416044161441624416344164441654416644167441684416944170441714417244173441744417544176441774417844179441804418144182441834418444185441864418744188441894419044191441924419344194441954419644197441984419944200442014420244203442044420544206442074420844209442104421144212442134421444215442164421744218442194422044221442224422344224442254422644227442284422944230442314423244233442344423544236442374423844239442404424144242442434424444245442464424744248442494425044251442524425344254442554425644257442584425944260442614426244263442644426544266442674426844269442704427144272442734427444275442764427744278442794428044281442824428344284442854428644287442884428944290442914429244293442944429544296442974429844299443004430144302443034430444305443064430744308443094431044311443124431344314443154431644317443184431944320443214432244323443244432544326443274432844329443304433144332443334433444335443364433744338443394434044341443424434344344443454434644347443484434944350443514435244353443544435544356443574435844359443604436144362443634436444365443664436744368443694437044371443724437344374443754437644377443784437944380443814438244383443844438544386443874438844389443904439144392443934439444395443964439744398443994440044401444024440344404444054440644407444084440944410444114441244413444144441544416444174441844419444204442144422444234442444425444264442744428444294443044431444324443344434444354443644437444384443944440444414444244443444444444544446444474444844449444504445144452444534445444455444564445744458444594446044461444624446344464444654446644467444684446944470444714447244473444744447544476444774447844479444804448144482444834448444485444864448744488444894449044491444924449344494444954449644497444984449944500445014450244503445044450544506445074450844509445104451144512445134451444515445164451744518445194452044521445224452344524445254452644527445284452944530445314453244533445344453544536445374453844539445404454144542445434454444545445464454744548445494455044551445524455344554445554455644557445584455944560445614456244563445644456544566445674456844569445704457144572445734457444575445764457744578445794458044581445824458344584445854458644587445884458944590445914459244593445944459544596445974459844599446004460144602446034460444605446064460744608446094461044611446124461344614446154461644617446184461944620446214462244623446244462544626446274462844629446304463144632446334463444635446364463744638446394464044641446424464344644446454464644647446484464944650446514465244653446544465544656446574465844659446604466144662446634466444665446664466744668446694467044671446724467344674446754467644677446784467944680446814468244683446844468544686446874468844689446904469144692446934469444695446964469744698446994470044701447024470344704447054470644707447084470944710447114471244713447144471544716447174471844719447204472144722447234472444725447264472744728447294473044731447324473344734447354473644737447384473944740447414474244743447444474544746447474474844749447504475144752447534475444755447564475744758447594476044761447624476344764447654476644767447684476944770447714477244773447744477544776447774477844779447804478144782447834478444785447864478744788447894479044791447924479344794447954479644797447984479944800448014480244803448044480544806448074480844809448104481144812448134481444815448164481744818448194482044821448224482344824448254482644827448284482944830448314483244833448344483544836448374483844839448404484144842448434484444845448464484744848448494485044851448524485344854448554485644857448584485944860448614486244863448644486544866448674486844869448704487144872448734487444875448764487744878448794488044881448824488344884448854488644887448884488944890448914489244893448944489544896448974489844899449004490144902449034490444905449064490744908449094491044911449124491344914449154491644917449184491944920449214492244923449244492544926449274492844929449304493144932449334493444935449364493744938449394494044941449424494344944449454494644947449484494944950449514495244953449544495544956449574495844959449604496144962449634496444965449664496744968449694497044971449724497344974449754497644977449784497944980449814498244983449844498544986449874498844989449904499144992449934499444995449964499744998449994500045001450024500345004450054500645007450084500945010450114501245013450144501545016450174501845019450204502145022450234502445025450264502745028450294503045031450324503345034450354503645037450384503945040450414504245043450444504545046450474504845049450504505145052450534505445055450564505745058450594506045061450624506345064450654506645067450684506945070450714507245073450744507545076450774507845079450804508145082450834508445085450864508745088450894509045091450924509345094450954509645097450984509945100451014510245103451044510545106451074510845109451104511145112451134511445115451164511745118451194512045121451224512345124451254512645127451284512945130451314513245133451344513545136451374513845139451404514145142451434514445145451464514745148451494515045151451524515345154451554515645157451584515945160451614516245163451644516545166451674516845169451704517145172451734517445175451764517745178451794518045181451824518345184451854518645187451884518945190451914519245193451944519545196451974519845199452004520145202452034520445205452064520745208452094521045211452124521345214452154521645217452184521945220452214522245223452244522545226452274522845229452304523145232452334523445235452364523745238452394524045241452424524345244452454524645247452484524945250452514525245253452544525545256452574525845259452604526145262452634526445265452664526745268452694527045271452724527345274452754527645277452784527945280452814528245283452844528545286452874528845289452904529145292452934529445295452964529745298452994530045301453024530345304453054530645307453084530945310453114531245313453144531545316453174531845319453204532145322453234532445325453264532745328453294533045331453324533345334453354533645337453384533945340453414534245343453444534545346453474534845349453504535145352453534535445355453564535745358453594536045361453624536345364453654536645367453684536945370453714537245373453744537545376453774537845379453804538145382453834538445385453864538745388453894539045391453924539345394453954539645397453984539945400454014540245403454044540545406454074540845409454104541145412454134541445415454164541745418454194542045421454224542345424454254542645427454284542945430454314543245433454344543545436454374543845439454404544145442454434544445445454464544745448454494545045451454524545345454454554545645457454584545945460454614546245463454644546545466454674546845469454704547145472454734547445475454764547745478454794548045481454824548345484454854548645487454884548945490454914549245493454944549545496454974549845499455004550145502455034550445505455064550745508455094551045511455124551345514455154551645517455184551945520455214552245523455244552545526455274552845529455304553145532455334553445535455364553745538455394554045541455424554345544455454554645547455484554945550455514555245553455544555545556455574555845559455604556145562455634556445565455664556745568455694557045571455724557345574455754557645577455784557945580455814558245583455844558545586455874558845589455904559145592455934559445595455964559745598455994560045601456024560345604456054560645607456084560945610456114561245613456144561545616456174561845619456204562145622456234562445625456264562745628456294563045631456324563345634456354563645637456384563945640456414564245643456444564545646456474564845649456504565145652456534565445655456564565745658456594566045661456624566345664456654566645667456684566945670456714567245673456744567545676456774567845679456804568145682456834568445685456864568745688456894569045691456924569345694456954569645697456984569945700457014570245703457044570545706457074570845709457104571145712457134571445715457164571745718457194572045721457224572345724457254572645727457284572945730457314573245733457344573545736457374573845739457404574145742457434574445745457464574745748457494575045751457524575345754457554575645757457584575945760457614576245763457644576545766457674576845769457704577145772457734577445775457764577745778457794578045781457824578345784457854578645787457884578945790457914579245793457944579545796457974579845799458004580145802458034580445805458064580745808458094581045811458124581345814458154581645817458184581945820458214582245823458244582545826458274582845829458304583145832458334583445835458364583745838458394584045841458424584345844458454584645847458484584945850458514585245853458544585545856458574585845859458604586145862458634586445865458664586745868458694587045871458724587345874458754587645877458784587945880458814588245883458844588545886458874588845889458904589145892458934589445895458964589745898458994590045901459024590345904459054590645907459084590945910459114591245913459144591545916459174591845919459204592145922459234592445925459264592745928459294593045931459324593345934459354593645937459384593945940459414594245943459444594545946459474594845949459504595145952459534595445955459564595745958459594596045961459624596345964459654596645967459684596945970459714597245973459744597545976459774597845979459804598145982459834598445985459864598745988459894599045991459924599345994459954599645997459984599946000460014600246003460044600546006460074600846009460104601146012460134601446015460164601746018460194602046021460224602346024460254602646027460284602946030460314603246033460344603546036460374603846039460404604146042460434604446045460464604746048460494605046051460524605346054460554605646057460584605946060460614606246063460644606546066460674606846069460704607146072460734607446075460764607746078460794608046081460824608346084460854608646087460884608946090460914609246093460944609546096460974609846099461004610146102461034610446105461064610746108461094611046111461124611346114461154611646117461184611946120461214612246123461244612546126461274612846129461304613146132461334613446135461364613746138461394614046141461424614346144461454614646147461484614946150461514615246153461544615546156461574615846159461604616146162461634616446165461664616746168461694617046171461724617346174461754617646177461784617946180461814618246183461844618546186461874618846189461904619146192461934619446195461964619746198461994620046201462024620346204462054620646207462084620946210462114621246213462144621546216462174621846219462204622146222462234622446225462264622746228462294623046231462324623346234462354623646237462384623946240462414624246243462444624546246462474624846249462504625146252462534625446255462564625746258462594626046261462624626346264462654626646267462684626946270462714627246273462744627546276462774627846279462804628146282462834628446285462864628746288462894629046291462924629346294462954629646297462984629946300463014630246303463044630546306463074630846309463104631146312463134631446315463164631746318463194632046321463224632346324463254632646327463284632946330463314633246333463344633546336463374633846339463404634146342463434634446345463464634746348463494635046351463524635346354463554635646357463584635946360463614636246363463644636546366463674636846369463704637146372463734637446375463764637746378463794638046381463824638346384463854638646387463884638946390463914639246393463944639546396463974639846399464004640146402464034640446405464064640746408464094641046411464124641346414464154641646417464184641946420464214642246423464244642546426464274642846429464304643146432464334643446435464364643746438464394644046441464424644346444464454644646447464484644946450464514645246453464544645546456464574645846459464604646146462464634646446465464664646746468464694647046471464724647346474464754647646477464784647946480464814648246483464844648546486464874648846489464904649146492464934649446495464964649746498464994650046501465024650346504465054650646507465084650946510465114651246513465144651546516465174651846519465204652146522465234652446525465264652746528465294653046531465324653346534465354653646537465384653946540465414654246543465444654546546465474654846549465504655146552465534655446555465564655746558465594656046561465624656346564465654656646567465684656946570465714657246573465744657546576465774657846579465804658146582465834658446585465864658746588465894659046591465924659346594465954659646597465984659946600466014660246603466044660546606466074660846609466104661146612466134661446615466164661746618466194662046621466224662346624466254662646627466284662946630466314663246633466344663546636466374663846639466404664146642466434664446645466464664746648466494665046651466524665346654466554665646657466584665946660466614666246663466644666546666466674666846669466704667146672466734667446675466764667746678466794668046681466824668346684466854668646687466884668946690466914669246693466944669546696466974669846699467004670146702467034670446705467064670746708467094671046711467124671346714467154671646717467184671946720467214672246723467244672546726467274672846729467304673146732467334673446735467364673746738467394674046741467424674346744467454674646747467484674946750467514675246753467544675546756467574675846759467604676146762467634676446765467664676746768467694677046771467724677346774467754677646777467784677946780467814678246783467844678546786467874678846789467904679146792467934679446795467964679746798467994680046801468024680346804468054680646807468084680946810468114681246813468144681546816468174681846819468204682146822468234682446825468264682746828468294683046831468324683346834468354683646837468384683946840468414684246843468444684546846468474684846849468504685146852468534685446855468564685746858468594686046861468624686346864468654686646867468684686946870468714687246873468744687546876468774687846879468804688146882468834688446885468864688746888468894689046891468924689346894468954689646897468984689946900469014690246903469044690546906469074690846909469104691146912469134691446915469164691746918469194692046921469224692346924469254692646927469284692946930469314693246933469344693546936469374693846939469404694146942469434694446945469464694746948469494695046951469524695346954469554695646957469584695946960469614696246963469644696546966469674696846969469704697146972469734697446975469764697746978469794698046981469824698346984469854698646987469884698946990469914699246993469944699546996469974699846999470004700147002470034700447005470064700747008470094701047011470124701347014470154701647017470184701947020470214702247023470244702547026470274702847029470304703147032470334703447035470364703747038470394704047041470424704347044470454704647047470484704947050470514705247053470544705547056470574705847059470604706147062470634706447065470664706747068470694707047071470724707347074470754707647077470784707947080470814708247083470844708547086470874708847089470904709147092470934709447095470964709747098470994710047101471024710347104471054710647107471084710947110471114711247113471144711547116471174711847119471204712147122471234712447125471264712747128471294713047131471324713347134471354713647137471384713947140471414714247143471444714547146471474714847149471504715147152471534715447155471564715747158471594716047161471624716347164471654716647167471684716947170471714717247173471744717547176471774717847179471804718147182471834718447185471864718747188471894719047191471924719347194471954719647197471984719947200472014720247203472044720547206472074720847209472104721147212472134721447215472164721747218472194722047221472224722347224472254722647227472284722947230472314723247233472344723547236472374723847239472404724147242472434724447245472464724747248472494725047251472524725347254472554725647257472584725947260472614726247263472644726547266472674726847269472704727147272472734727447275472764727747278472794728047281472824728347284472854728647287472884728947290472914729247293472944729547296472974729847299473004730147302473034730447305473064730747308473094731047311473124731347314473154731647317473184731947320473214732247323473244732547326473274732847329473304733147332473334733447335473364733747338473394734047341473424734347344473454734647347473484734947350473514735247353473544735547356473574735847359473604736147362473634736447365473664736747368473694737047371473724737347374473754737647377473784737947380473814738247383473844738547386473874738847389473904739147392473934739447395473964739747398473994740047401474024740347404474054740647407474084740947410474114741247413474144741547416474174741847419474204742147422474234742447425474264742747428474294743047431474324743347434474354743647437474384743947440474414744247443474444744547446474474744847449474504745147452474534745447455474564745747458474594746047461474624746347464474654746647467474684746947470474714747247473474744747547476474774747847479474804748147482474834748447485474864748747488474894749047491474924749347494474954749647497474984749947500475014750247503475044750547506475074750847509475104751147512475134751447515475164751747518475194752047521475224752347524475254752647527475284752947530475314753247533475344753547536475374753847539475404754147542475434754447545475464754747548475494755047551475524755347554475554755647557475584755947560475614756247563475644756547566475674756847569475704757147572475734757447575475764757747578475794758047581475824758347584475854758647587475884758947590475914759247593475944759547596475974759847599476004760147602476034760447605476064760747608476094761047611476124761347614476154761647617476184761947620476214762247623476244762547626476274762847629476304763147632476334763447635476364763747638476394764047641476424764347644476454764647647476484764947650476514765247653476544765547656476574765847659476604766147662476634766447665476664766747668476694767047671476724767347674476754767647677476784767947680476814768247683476844768547686476874768847689476904769147692476934769447695476964769747698476994770047701477024770347704477054770647707477084770947710477114771247713477144771547716477174771847719477204772147722477234772447725477264772747728477294773047731477324773347734477354773647737477384773947740477414774247743477444774547746477474774847749477504775147752477534775447755477564775747758477594776047761477624776347764477654776647767477684776947770477714777247773477744777547776477774777847779477804778147782477834778447785477864778747788477894779047791477924779347794477954779647797477984779947800478014780247803478044780547806478074780847809478104781147812478134781447815478164781747818478194782047821478224782347824478254782647827478284782947830478314783247833478344783547836478374783847839478404784147842478434784447845478464784747848478494785047851478524785347854478554785647857478584785947860478614786247863478644786547866478674786847869478704787147872478734787447875478764787747878478794788047881478824788347884478854788647887478884788947890478914789247893478944789547896478974789847899479004790147902479034790447905479064790747908479094791047911479124791347914479154791647917479184791947920479214792247923479244792547926479274792847929479304793147932479334793447935479364793747938479394794047941479424794347944479454794647947479484794947950479514795247953479544795547956479574795847959479604796147962479634796447965479664796747968479694797047971479724797347974479754797647977479784797947980479814798247983479844798547986479874798847989479904799147992479934799447995479964799747998479994800048001480024800348004480054800648007480084800948010480114801248013480144801548016480174801848019480204802148022480234802448025480264802748028480294803048031480324803348034480354803648037480384803948040480414804248043480444804548046480474804848049480504805148052480534805448055480564805748058480594806048061480624806348064480654806648067480684806948070480714807248073480744807548076480774807848079480804808148082480834808448085480864808748088480894809048091480924809348094480954809648097480984809948100481014810248103481044810548106481074810848109481104811148112481134811448115481164811748118481194812048121481224812348124481254812648127481284812948130481314813248133481344813548136481374813848139481404814148142481434814448145481464814748148481494815048151481524815348154481554815648157481584815948160481614816248163481644816548166481674816848169481704817148172481734817448175481764817748178481794818048181481824818348184481854818648187481884818948190481914819248193481944819548196481974819848199482004820148202482034820448205482064820748208482094821048211482124821348214482154821648217482184821948220482214822248223482244822548226482274822848229482304823148232482334823448235482364823748238482394824048241482424824348244482454824648247482484824948250482514825248253482544825548256482574825848259482604826148262482634826448265482664826748268482694827048271482724827348274482754827648277482784827948280482814828248283482844828548286482874828848289482904829148292482934829448295482964829748298482994830048301483024830348304483054830648307483084830948310483114831248313483144831548316483174831848319483204832148322483234832448325483264832748328483294833048331483324833348334483354833648337483384833948340483414834248343483444834548346483474834848349483504835148352483534835448355483564835748358483594836048361483624836348364483654836648367483684836948370483714837248373483744837548376483774837848379483804838148382483834838448385483864838748388483894839048391483924839348394483954839648397483984839948400484014840248403484044840548406484074840848409484104841148412484134841448415484164841748418484194842048421484224842348424484254842648427484284842948430484314843248433484344843548436484374843848439484404844148442484434844448445484464844748448484494845048451484524845348454484554845648457484584845948460484614846248463484644846548466484674846848469484704847148472484734847448475484764847748478484794848048481484824848348484484854848648487484884848948490484914849248493484944849548496484974849848499485004850148502485034850448505485064850748508485094851048511485124851348514485154851648517485184851948520485214852248523485244852548526485274852848529485304853148532485334853448535485364853748538485394854048541485424854348544485454854648547485484854948550485514855248553485544855548556485574855848559485604856148562485634856448565485664856748568485694857048571485724857348574485754857648577485784857948580485814858248583485844858548586485874858848589485904859148592485934859448595485964859748598485994860048601486024860348604486054860648607486084860948610486114861248613486144861548616486174861848619486204862148622486234862448625 |
- // #include "config/version.h"
- #ifndef ENTT_CONFIG_VERSION_H
- #define ENTT_CONFIG_VERSION_H
- #define ENTT_VERSION_MAJOR 3
- #define ENTT_VERSION_MINOR 8
- #define ENTT_VERSION_PATCH 0
- #endif
- // #include "core/algorithm.hpp"
- #ifndef ENTT_CORE_ALGORITHM_HPP
- #define ENTT_CORE_ALGORITHM_HPP
- #include <vector>
- #include <utility>
- #include <iterator>
- #include <algorithm>
- #include <functional>
- // #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
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_NOEXCEPT noexcept
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_NOEXCEPT
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606L
- # include <new>
- # define ENTT_LAUNDER(expr) std::launder(expr)
- #else
- # define ENTT_LAUNDER(expr) expr
- #endif
- #ifndef ENTT_USE_ATOMIC
- # define ENTT_MAYBE_ATOMIC(Type) Type
- #else
- # include <atomic>
- # define ENTT_MAYBE_ATOMIC(Type) std::atomic<Type>
- #endif
- #ifndef ENTT_ID_TYPE
- # include <cstdint>
- # define ENTT_ID_TYPE std::uint32_t
- #endif
- #ifdef ENTT_SPARSE_PAGE
- static_assert(ENTT_SPARSE_PAGE && ((ENTT_SPARSE_PAGE & (ENTT_SPARSE_PAGE - 1)) == 0), "ENTT_SPARSE_PAGE must be a power of two");
- #else
- # define ENTT_SPARSE_PAGE 4096
- #endif
- #ifdef ENTT_PACKED_PAGE
- static_assert(ENTT_PACKED_PAGE && ((ENTT_PACKED_PAGE & (ENTT_PACKED_PAGE - 1)) == 0), "ENTT_PACKED_PAGE must be a power of two");
- #else
- # 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
- # include <type_traits>
- # define ENTT_IGNORE_IF_EMPTY std::false_type
- #else
- # include <type_traits>
- # define ENTT_IGNORE_IF_EMPTY std::true_type
- #endif
- #ifndef ENTT_STANDARD_CPP
- # 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
- #endif
- namespace entt {
- /*! @brief Identity function object (waiting for C++20). */
- struct identity {
- /**
- * @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;
- };
- }
- #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);
- }
- }
- }
- };
- }
- #endif
- // #include "core/any.hpp"
- #ifndef ENTT_CORE_ANY_HPP
- #define ENTT_CORE_ANY_HPP
- #include <cstddef>
- #include <functional>
- #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
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_NOEXCEPT noexcept
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_NOEXCEPT
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606L
- # include <new>
- # define ENTT_LAUNDER(expr) std::launder(expr)
- #else
- # define ENTT_LAUNDER(expr) expr
- #endif
- #ifndef ENTT_USE_ATOMIC
- # define ENTT_MAYBE_ATOMIC(Type) Type
- #else
- # include <atomic>
- # define ENTT_MAYBE_ATOMIC(Type) std::atomic<Type>
- #endif
- #ifndef ENTT_ID_TYPE
- # include <cstdint>
- # define ENTT_ID_TYPE std::uint32_t
- #endif
- #ifdef ENTT_SPARSE_PAGE
- static_assert(ENTT_SPARSE_PAGE && ((ENTT_SPARSE_PAGE & (ENTT_SPARSE_PAGE - 1)) == 0), "ENTT_SPARSE_PAGE must be a power of two");
- #else
- # define ENTT_SPARSE_PAGE 4096
- #endif
- #ifdef ENTT_PACKED_PAGE
- static_assert(ENTT_PACKED_PAGE && ((ENTT_PACKED_PAGE & (ENTT_PACKED_PAGE - 1)) == 0), "ENTT_PACKED_PAGE must be a power of two");
- #else
- # 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
- # include <type_traits>
- # define ENTT_IGNORE_IF_EMPTY std::false_type
- #else
- # include <type_traits>
- # define ENTT_IGNORE_IF_EMPTY std::true_type
- #endif
- #ifndef ENTT_STANDARD_CPP
- # 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
- #endif
- namespace entt {
- /*! @brief Identity function object (waiting for C++20). */
- struct identity {
- /**
- * @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;
- };
- }
- #endif
- // #include "fwd.hpp"
- #ifndef ENTT_CORE_FWD_HPP
- #define ENTT_CORE_FWD_HPP
- #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<>;
- }
- #endif
- // #include "type_info.hpp"
- #ifndef ENTT_CORE_TYPE_INFO_HPP
- #define ENTT_CORE_TYPE_INFO_HPP
- #include <string_view>
- #include <type_traits>
- // #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 "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;
- };
- }
- /**
- * 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 identifers 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.
- *
- * @tparam Char Character type.
- */
- template<typename Char>
- class basic_hashed_string {
- using traits_type = internal::fnv1a_traits<id_type>;
- struct const_wrapper {
- // non-explicit constructor on purpose
- constexpr const_wrapper(const Char *curr) ENTT_NOEXCEPT: str{curr} {}
- const Char *str;
- };
- // Fowler–Noll–Vo hash function v. 1a - the good
- [[nodiscard]] static constexpr id_type helper(const Char *curr) ENTT_NOEXCEPT {
- auto value = traits_type::offset;
- while(*curr != 0) {
- value = (value ^ static_cast<traits_type::type>(*(curr++))) * traits_type::prime;
- }
- return value;
- }
- public:
- /*! @brief Character type. */
- using value_type = Char;
- /*! @brief Unsigned integer type. */
- using hash_type = id_type;
- /**
- * @brief Returns directly the numeric representation of a string view.
- * @param str Human-readable identifer.
- * @param size Length of the string to hash.
- * @return The numeric representation of the string.
- */
- [[nodiscard]] static constexpr hash_type value(const value_type *str, std::size_t size) ENTT_NOEXCEPT {
- id_type partial{traits_type::offset};
- while(size--) { partial = (partial^(str++)[0])*traits_type::prime; }
- return partial;
- }
- /**
- * @brief Returns directly the numeric representation of a string.
- *
- * Forcing template resolution avoids implicit conversions. An
- * human-readable identifier can be anything but a plain, old bunch of
- * characters.<br/>
- * Example of use:
- * @code{.cpp}
- * const auto value = basic_hashed_string<char>::to_value("my.png");
- * @endcode
- *
- * @tparam N Number of characters of the identifier.
- * @param str Human-readable identifer.
- * @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 helper(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 hash_type value(const_wrapper wrapper) ENTT_NOEXCEPT {
- return helper(wrapper.str);
- }
- /*! @brief Constructs an empty hashed string. */
- constexpr basic_hashed_string() ENTT_NOEXCEPT
- : str{nullptr}, hash{}
- {}
- /**
- * @brief Constructs a hashed string from an array of const characters.
- *
- * Forcing template resolution avoids implicit conversions. An
- * human-readable identifier can be anything but a plain, old bunch of
- * characters.<br/>
- * Example of use:
- * @code{.cpp}
- * basic_hashed_string<char> hs{"my.png"};
- * @endcode
- *
- * @tparam N Number of characters of the identifier.
- * @param curr Human-readable identifer.
- */
- template<std::size_t N>
- constexpr basic_hashed_string(const value_type (&curr)[N]) ENTT_NOEXCEPT
- : str{curr}, hash{helper(curr)}
- {}
- /**
- * @brief Explicit constructor on purpose to avoid constructing a hashed
- * string directly from a `const value_type *`.
- * @param wrapper Helps achieving the purpose by relying on overloading.
- */
- explicit constexpr basic_hashed_string(const_wrapper wrapper) ENTT_NOEXCEPT
- : str{wrapper.str}, hash{helper(wrapper.str)}
- {}
- /**
- * @brief Returns the human-readable representation of a hashed string.
- * @return The string used to initialize the instance.
- */
- [[nodiscard]] constexpr const value_type * data() const ENTT_NOEXCEPT {
- return str;
- }
- /**
- * @brief Returns the numeric representation of a hashed string.
- * @return The numeric representation of the instance.
- */
- [[nodiscard]] constexpr hash_type value() const ENTT_NOEXCEPT {
- return 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 instance.
- */
- [[nodiscard]] constexpr operator hash_type() const ENTT_NOEXCEPT { return value(); }
- /**
- * @brief Compares two hashed strings.
- * @param other Hashed string with which to compare.
- * @return True if the two hashed strings are identical, false otherwise.
- */
- [[nodiscard]] constexpr bool operator==(const basic_hashed_string &other) const ENTT_NOEXCEPT {
- return hash == other.hash;
- }
- private:
- const value_type *str;
- hash_type hash;
- };
- /**
- * @brief Deduction guide.
- *
- * It allows to deduce the character type of the hashed string directly from a
- * human-readable identifer provided to the constructor.
- *
- * @tparam Char Character type.
- * @tparam N Number of characters of the identifier.
- * @param str Human-readable identifer.
- */
- 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 == 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 entt::hashed_string operator"" _hs(const char *str, std::size_t) ENTT_NOEXCEPT {
- return entt::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 entt::hashed_wstring operator"" _hws(const wchar_t *str, std::size_t) ENTT_NOEXCEPT {
- return entt::hashed_wstring{str};
- }
- }
- }
- #endif
- // #include "fwd.hpp"
- namespace entt {
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- namespace internal {
- struct ENTT_API type_seq 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;
- }
- }
- /**
- * 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_seq 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_seq::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_seq<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. */
- class type_info final {
- template<typename>
- friend type_info type_id() ENTT_NOEXCEPT;
- type_info(id_type seq_v, id_type hash_v, std::string_view name_v) ENTT_NOEXCEPT
- : seq_value{seq_v},
- hash_value{hash_v},
- name_value{name_v}
- {}
- public:
- /*! @brief Default constructor. */
- type_info() ENTT_NOEXCEPT
- : type_info({}, {}, {})
- {}
- /*! @brief Default copy constructor. */
- type_info(const type_info &) ENTT_NOEXCEPT = default;
- /*! @brief Default move constructor. */
- type_info(type_info &&) ENTT_NOEXCEPT = default;
- /**
- * @brief Default copy assignment operator.
- * @return This type info object.
- */
- type_info & operator=(const type_info &) ENTT_NOEXCEPT = default;
- /**
- * @brief Default move assignment operator.
- * @return This type info object.
- */
- type_info & operator=(type_info &&) ENTT_NOEXCEPT = default;
- /**
- * @brief Checks if a type info object is properly initialized.
- * @return True if the object is properly initialized, false otherwise.
- */
- [[nodiscard]] explicit operator bool() const ENTT_NOEXCEPT {
- return name_value.data() != nullptr;
- }
- /**
- * @brief Type sequential identifier.
- * @return Type sequential identifier.
- */
- [[nodiscard]] id_type seq() const ENTT_NOEXCEPT {
- return seq_value;
- }
- /**
- * @brief Type hash.
- * @return Type hash.
- */
- [[nodiscard]] id_type hash() const ENTT_NOEXCEPT {
- return hash_value;
- }
- /**
- * @brief Type name.
- * @return Type name.
- */
- [[nodiscard]] std::string_view name() const ENTT_NOEXCEPT {
- return name_value;
- }
- /**
- * @brief Compares the contents of two type info objects.
- * @param other Object with which to compare.
- * @return False if the two contents differ, true otherwise.
- */
- [[nodiscard]] bool operator==(const type_info &other) const ENTT_NOEXCEPT {
- return hash_value == other.hash_value;
- }
- private:
- id_type seq_value;
- id_type hash_value;
- std::string_view name_value;
- };
- /**
- * @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 contents differ, false otherwise.
- */
- [[nodiscard]] inline bool operator!=(const type_info &lhs, const type_info &rhs) ENTT_NOEXCEPT {
- return !(lhs == rhs);
- }
- /**
- * @brief Returns the type info object for a given type.
- * @tparam Type Type for which to generate a type info object.
- * @return The type info object for the given type.
- */
- template<typename Type>
- [[nodiscard]] type_info type_id() ENTT_NOEXCEPT {
- return type_info{
- type_seq<std::remove_cv_t<std::remove_reference_t<Type>>>::value(),
- type_hash<std::remove_cv_t<std::remove_reference_t<Type>>>::value(),
- type_name<std::remove_cv_t<std::remove_reference_t<Type>>>::value()
- };
- }
- }
- #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<class 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_t = 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_v = 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::disjunction_v<std::is_same<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<class 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;
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- namespace internal {
- template<typename>
- [[nodiscard]] constexpr bool is_equality_comparable(...) { return false; }
- template<typename Type>
- [[nodiscard]] constexpr auto is_equality_comparable(choice_t<0>)
- -> decltype(std::declval<Type>() == std::declval<Type>()) { return true; }
- template<typename Type>
- [[nodiscard]] constexpr auto is_equality_comparable(choice_t<1>)
- -> decltype(std::declval<typename Type::value_type>(), std::declval<Type>() == std::declval<Type>()) {
- if constexpr(std::is_same_v<typename Type::value_type, Type>) {
- return is_equality_comparable<Type>(choice<0>);
- } else {
- return is_equality_comparable<typename Type::value_type>(choice<2>);
- }
- }
- template<typename Type>
- [[nodiscard]] constexpr auto is_equality_comparable(choice_t<2>)
- -> decltype(std::declval<typename Type::mapped_type>(), std::declval<Type>() == std::declval<Type>()) {
- return is_equality_comparable<typename Type::key_type>(choice<2>) && is_equality_comparable<typename Type::mapped_type>(choice<2>);
- }
- }
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /**
- * @brief Provides the member constant `value` to true if a given type is
- * equality comparable, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_equality_comparable: std::bool_constant<internal::is_equality_comparable<Type>(choice<2>)> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<class Type>
- inline constexpr bool is_equality_comparable_v = is_equality_comparable<Type>::value;
- /*! @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 {};
- /*! @copydoc is_iterator */
- template<typename Type>
- struct is_iterator<Type, std::void_t<typename std::iterator_traits<Type>::iterator_category>>
- : std::true_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 of the
- * required iterator type, false otherwise.
- * @tparam Type The type to test.
- * @tparam It Required iterator type.
- */
- template<typename Type, typename It, typename = void>
- struct is_iterator_type: std::false_type {};
- /*! @copydoc is_iterator_type */
- template<typename Type, typename It>
- struct is_iterator_type<Type, It, std::enable_if_t<is_iterator_v<Type> && std::is_same_v<Type, It>>>
- : std::true_type
- {};
- /*! @copydoc is_iterator_type */
- template<typename Type, typename It>
- struct is_iterator_type<Type, It, std::enable_if_t<!std::is_same_v<Type, It>, std::void_t<typename It::iterator_type>>>
- : is_iterator_type<Type, typename It::iterator_type>
- {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- * @tparam It Required iterator type.
- */
- template<typename Type, typename It>
- inline constexpr bool is_iterator_type_v = is_iterator_type<Type, It>::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;
- }
- #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, DTOR, COMP, ADDR, CADDR, TYPE };
- 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 &, 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>
- [[nodiscard]] static constexpr policy type_to_policy() {
- if constexpr(std::is_lvalue_reference_v<Type>) {
- if constexpr(std::is_const_v<std::remove_reference_t<Type>>) {
- return policy::CREF;
- } else {
- return policy::REF;
- }
- } else {
- return policy::OWNER;
- }
- }
- template<typename Type>
- [[nodiscard]] static bool compare(const void *lhs, const void *rhs) {
- if constexpr(!std::is_function_v<Type> && is_equality_comparable_v<Type>) {
- return *static_cast<const Type *>(lhs) == *static_cast<const Type *>(rhs);
- } else {
- return lhs == rhs;
- }
- }
- template<typename Type>
- static const void * basic_vtable([[maybe_unused]] const operation op, [[maybe_unused]] const basic_any &from, [[maybe_unused]] void *to) {
- static_assert(std::is_same_v<std::remove_reference_t<std::remove_const_t<Type>>, Type>, "Invalid type");
- if constexpr(!std::is_void_v<Type>) {
- const Type *instance = (in_situ<Type> && from.mode == policy::OWNER)
- ? ENTT_LAUNDER(reinterpret_cast<const Type *>(&from.storage))
- : static_cast<const Type *>(from.instance);
- switch(op) {
- case operation::COPY:
- if constexpr(std::is_copy_constructible_v<Type>) {
- static_cast<basic_any *>(to)->emplace<Type>(*instance);
- }
- break;
- case operation::MOVE:
- if constexpr(in_situ<Type>) {
- if(from.mode == policy::OWNER) {
- return new (&static_cast<basic_any *>(to)->storage) Type{std::move(*const_cast<Type *>(instance))};
- }
- }
- return (static_cast<basic_any *>(to)->instance = std::exchange(const_cast<basic_any &>(from).instance, nullptr));
- case operation::DTOR:
- if(from.mode == policy::OWNER) {
- if constexpr(in_situ<Type>) {
- instance->~Type();
- } else if constexpr(std::is_array_v<Type>) {
- delete[] instance;
- } else {
- delete instance;
- }
- }
- break;
- case operation::COMP:
- return compare<Type>(instance, (*static_cast<const basic_any **>(to))->data()) ? to : nullptr;
- case operation::ADDR:
- if(from.mode == policy::CREF) {
- return nullptr;
- }
- [[fallthrough]];
- case operation::CADDR:
- return instance;
- case operation::TYPE:
- *static_cast<type_info *>(to) = type_id<Type>();
- break;
- }
- }
- return nullptr;
- }
- template<typename Type, typename... Args>
- void initialize([[maybe_unused]] Args &&... args) {
- if constexpr(!std::is_void_v<Type>) {
- if constexpr(std::is_lvalue_reference_v<Type>) {
- static_assert(sizeof...(Args) == 1u && (std::is_lvalue_reference_v<Args> && ...), "Invalid arguments");
- 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()},
- 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. */
- basic_any() ENTT_NOEXCEPT
- : instance{},
- vtable{&basic_vtable<void>},
- 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)
- : instance{},
- vtable{&basic_vtable<std::remove_const_t<std::remove_reference_t<Type>>>},
- mode{type_to_policy<Type>()}
- {
- initialize<Type>(std::forward<Args>(args)...);
- }
- /**
- * @brief Constructs a wrapper that holds an unmanaged object.
- * @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>
- basic_any(std::reference_wrapper<Type> value) ENTT_NOEXCEPT
- : basic_any{}
- {
- // invokes deprecated assignment operator (and avoids issues with vs2017)
- *this = value;
- }
- /**
- * @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)
- : instance{},
- vtable{&basic_vtable<std::decay_t<Type>>},
- mode{policy::OWNER}
- {
- 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)
- : instance{},
- vtable{&basic_vtable<void>},
- mode{policy::OWNER}
- {
- other.vtable(operation::COPY, other, this);
- }
- /**
- * @brief Move constructor.
- * @param other The instance to move from.
- */
- basic_any(basic_any &&other) ENTT_NOEXCEPT
- : instance{},
- vtable{other.vtable},
- mode{other.mode}
- {
- vtable(operation::MOVE, other, this);
- }
- /*! @brief Frees the internal storage, whatever it means. */
- ~basic_any() {
- vtable(operation::DTOR, *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();
- 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 {
- std::exchange(vtable, other.vtable)(operation::DTOR, *this, nullptr);
- other.vtable(operation::MOVE, other, this);
- 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>
- [[deprecated("Use std::in_place_type<T &>, entt::make_any<T &>, emplace<Type &> or forward_as_any instead")]]
- basic_any & operator=(std::reference_wrapper<Type> value) ENTT_NOEXCEPT {
- emplace<Type &>(value.get());
- 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 type of the contained object.
- * @return The type of the contained object, if any.
- */
- [[nodiscard]] type_info type() const ENTT_NOEXCEPT {
- type_info info{};
- vtable(operation::TYPE, *this, &info);
- 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(operation::CADDR, *this, nullptr);
- }
- /*! @copydoc data */
- [[nodiscard]] void * data() ENTT_NOEXCEPT {
- return const_cast<void *>(vtable(operation::ADDR, *this, 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) {
- std::exchange(vtable, &basic_vtable<std::remove_const_t<std::remove_reference_t<Type>>>)(operation::DTOR, *this, nullptr);
- mode = type_to_policy<Type>();
- initialize<Type>(std::forward<Args>(args)...);
- }
- /*! @brief Destroys contained object */
- void reset() {
- std::exchange(vtable, &basic_vtable<void>)(operation::DTOR, *this, 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(operation::CADDR, *this, nullptr) == 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 {
- const basic_any *trampoline = &other;
- return type() == other.type() && (vtable(operation::COMP, *this, &trampoline) || !other.data());
- }
- /**
- * @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; };
- 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 {
- // 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>(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 {
- return (data->type() == type_id<Type>() ? static_cast<const Type *>(data->data()) : nullptr);
- }
- /*! @copydoc any_cast */
- template<typename Type, std::size_t Len, std::size_t Align>
- Type * any_cast(basic_any<Len, Align> *data) ENTT_NOEXCEPT {
- // last attempt to make wrappers for const references return their values
- return (data->type() == type_id<Type>() ? static_cast<Type *>(static_cast<constness_as_t<basic_any<Len, Align>, Type> *>(data)->data()) : nullptr);
- }
- /**
- * @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)};
- }
- }
- #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/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++;
- };
- }
- #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;
- };
- }
- /**
- * 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 identifers 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.
- *
- * @tparam Char Character type.
- */
- template<typename Char>
- class basic_hashed_string {
- using traits_type = internal::fnv1a_traits<id_type>;
- struct const_wrapper {
- // non-explicit constructor on purpose
- constexpr const_wrapper(const Char *curr) ENTT_NOEXCEPT: str{curr} {}
- const Char *str;
- };
- // Fowler–Noll–Vo hash function v. 1a - the good
- [[nodiscard]] static constexpr id_type helper(const Char *curr) ENTT_NOEXCEPT {
- auto value = traits_type::offset;
- while(*curr != 0) {
- value = (value ^ static_cast<traits_type::type>(*(curr++))) * traits_type::prime;
- }
- return value;
- }
- public:
- /*! @brief Character type. */
- using value_type = Char;
- /*! @brief Unsigned integer type. */
- using hash_type = id_type;
- /**
- * @brief Returns directly the numeric representation of a string view.
- * @param str Human-readable identifer.
- * @param size Length of the string to hash.
- * @return The numeric representation of the string.
- */
- [[nodiscard]] static constexpr hash_type value(const value_type *str, std::size_t size) ENTT_NOEXCEPT {
- id_type partial{traits_type::offset};
- while(size--) { partial = (partial^(str++)[0])*traits_type::prime; }
- return partial;
- }
- /**
- * @brief Returns directly the numeric representation of a string.
- *
- * Forcing template resolution avoids implicit conversions. An
- * human-readable identifier can be anything but a plain, old bunch of
- * characters.<br/>
- * Example of use:
- * @code{.cpp}
- * const auto value = basic_hashed_string<char>::to_value("my.png");
- * @endcode
- *
- * @tparam N Number of characters of the identifier.
- * @param str Human-readable identifer.
- * @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 helper(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 hash_type value(const_wrapper wrapper) ENTT_NOEXCEPT {
- return helper(wrapper.str);
- }
- /*! @brief Constructs an empty hashed string. */
- constexpr basic_hashed_string() ENTT_NOEXCEPT
- : str{nullptr}, hash{}
- {}
- /**
- * @brief Constructs a hashed string from an array of const characters.
- *
- * Forcing template resolution avoids implicit conversions. An
- * human-readable identifier can be anything but a plain, old bunch of
- * characters.<br/>
- * Example of use:
- * @code{.cpp}
- * basic_hashed_string<char> hs{"my.png"};
- * @endcode
- *
- * @tparam N Number of characters of the identifier.
- * @param curr Human-readable identifer.
- */
- template<std::size_t N>
- constexpr basic_hashed_string(const value_type (&curr)[N]) ENTT_NOEXCEPT
- : str{curr}, hash{helper(curr)}
- {}
- /**
- * @brief Explicit constructor on purpose to avoid constructing a hashed
- * string directly from a `const value_type *`.
- * @param wrapper Helps achieving the purpose by relying on overloading.
- */
- explicit constexpr basic_hashed_string(const_wrapper wrapper) ENTT_NOEXCEPT
- : str{wrapper.str}, hash{helper(wrapper.str)}
- {}
- /**
- * @brief Returns the human-readable representation of a hashed string.
- * @return The string used to initialize the instance.
- */
- [[nodiscard]] constexpr const value_type * data() const ENTT_NOEXCEPT {
- return str;
- }
- /**
- * @brief Returns the numeric representation of a hashed string.
- * @return The numeric representation of the instance.
- */
- [[nodiscard]] constexpr hash_type value() const ENTT_NOEXCEPT {
- return 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 instance.
- */
- [[nodiscard]] constexpr operator hash_type() const ENTT_NOEXCEPT { return value(); }
- /**
- * @brief Compares two hashed strings.
- * @param other Hashed string with which to compare.
- * @return True if the two hashed strings are identical, false otherwise.
- */
- [[nodiscard]] constexpr bool operator==(const basic_hashed_string &other) const ENTT_NOEXCEPT {
- return hash == other.hash;
- }
- private:
- const value_type *str;
- hash_type hash;
- };
- /**
- * @brief Deduction guide.
- *
- * It allows to deduce the character type of the hashed string directly from a
- * human-readable identifer provided to the constructor.
- *
- * @tparam Char Character type.
- * @tparam N Number of characters of the identifier.
- * @param str Human-readable identifer.
- */
- 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 == 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 entt::hashed_string operator"" _hs(const char *str, std::size_t) ENTT_NOEXCEPT {
- return entt::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 entt::hashed_wstring operator"" _hws(const wchar_t *str, std::size_t) ENTT_NOEXCEPT {
- return entt::hashed_wstring{str};
- }
- }
- }
- #endif
- // #include "core/ident.hpp"
- #ifndef ENTT_CORE_IDENT_HPP
- #define ENTT_CORE_IDENT_HPP
- #include <cstddef>
- #include <utility>
- #include <type_traits>
- // #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...>) {
- static_assert(std::disjunction_v<std::is_same<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...>{});
- };
- }
- #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 = {};
- }
- #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 "../config/config.h"
- // #include "../core/attribute.h"
- // #include "hashed_string.hpp"
- // #include "fwd.hpp"
- namespace entt {
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- namespace internal {
- struct ENTT_API type_seq 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;
- }
- }
- /**
- * 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_seq 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_seq::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_seq<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. */
- class type_info final {
- template<typename>
- friend type_info type_id() ENTT_NOEXCEPT;
- type_info(id_type seq_v, id_type hash_v, std::string_view name_v) ENTT_NOEXCEPT
- : seq_value{seq_v},
- hash_value{hash_v},
- name_value{name_v}
- {}
- public:
- /*! @brief Default constructor. */
- type_info() ENTT_NOEXCEPT
- : type_info({}, {}, {})
- {}
- /*! @brief Default copy constructor. */
- type_info(const type_info &) ENTT_NOEXCEPT = default;
- /*! @brief Default move constructor. */
- type_info(type_info &&) ENTT_NOEXCEPT = default;
- /**
- * @brief Default copy assignment operator.
- * @return This type info object.
- */
- type_info & operator=(const type_info &) ENTT_NOEXCEPT = default;
- /**
- * @brief Default move assignment operator.
- * @return This type info object.
- */
- type_info & operator=(type_info &&) ENTT_NOEXCEPT = default;
- /**
- * @brief Checks if a type info object is properly initialized.
- * @return True if the object is properly initialized, false otherwise.
- */
- [[nodiscard]] explicit operator bool() const ENTT_NOEXCEPT {
- return name_value.data() != nullptr;
- }
- /**
- * @brief Type sequential identifier.
- * @return Type sequential identifier.
- */
- [[nodiscard]] id_type seq() const ENTT_NOEXCEPT {
- return seq_value;
- }
- /**
- * @brief Type hash.
- * @return Type hash.
- */
- [[nodiscard]] id_type hash() const ENTT_NOEXCEPT {
- return hash_value;
- }
- /**
- * @brief Type name.
- * @return Type name.
- */
- [[nodiscard]] std::string_view name() const ENTT_NOEXCEPT {
- return name_value;
- }
- /**
- * @brief Compares the contents of two type info objects.
- * @param other Object with which to compare.
- * @return False if the two contents differ, true otherwise.
- */
- [[nodiscard]] bool operator==(const type_info &other) const ENTT_NOEXCEPT {
- return hash_value == other.hash_value;
- }
- private:
- id_type seq_value;
- id_type hash_value;
- std::string_view name_value;
- };
- /**
- * @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 contents differ, false otherwise.
- */
- [[nodiscard]] inline bool operator!=(const type_info &lhs, const type_info &rhs) ENTT_NOEXCEPT {
- return !(lhs == rhs);
- }
- /**
- * @brief Returns the type info object for a given type.
- * @tparam Type Type for which to generate a type info object.
- * @return The type info object for the given type.
- */
- template<typename Type>
- [[nodiscard]] type_info type_id() ENTT_NOEXCEPT {
- return type_info{
- type_seq<std::remove_cv_t<std::remove_reference_t<Type>>>::value(),
- type_hash<std::remove_cv_t<std::remove_reference_t<Type>>>::value(),
- type_name<std::remove_cv_t<std::remove_reference_t<Type>>>::value()
- };
- }
- }
- #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<class 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_t = 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_v = 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::disjunction_v<std::is_same<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<class 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;
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- namespace internal {
- template<typename>
- [[nodiscard]] constexpr bool is_equality_comparable(...) { return false; }
- template<typename Type>
- [[nodiscard]] constexpr auto is_equality_comparable(choice_t<0>)
- -> decltype(std::declval<Type>() == std::declval<Type>()) { return true; }
- template<typename Type>
- [[nodiscard]] constexpr auto is_equality_comparable(choice_t<1>)
- -> decltype(std::declval<typename Type::value_type>(), std::declval<Type>() == std::declval<Type>()) {
- if constexpr(std::is_same_v<typename Type::value_type, Type>) {
- return is_equality_comparable<Type>(choice<0>);
- } else {
- return is_equality_comparable<typename Type::value_type>(choice<2>);
- }
- }
- template<typename Type>
- [[nodiscard]] constexpr auto is_equality_comparable(choice_t<2>)
- -> decltype(std::declval<typename Type::mapped_type>(), std::declval<Type>() == std::declval<Type>()) {
- return is_equality_comparable<typename Type::key_type>(choice<2>) && is_equality_comparable<typename Type::mapped_type>(choice<2>);
- }
- }
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /**
- * @brief Provides the member constant `value` to true if a given type is
- * equality comparable, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_equality_comparable: std::bool_constant<internal::is_equality_comparable<Type>(choice<2>)> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<class Type>
- inline constexpr bool is_equality_comparable_v = is_equality_comparable<Type>::value;
- /*! @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 {};
- /*! @copydoc is_iterator */
- template<typename Type>
- struct is_iterator<Type, std::void_t<typename std::iterator_traits<Type>::iterator_category>>
- : std::true_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 of the
- * required iterator type, false otherwise.
- * @tparam Type The type to test.
- * @tparam It Required iterator type.
- */
- template<typename Type, typename It, typename = void>
- struct is_iterator_type: std::false_type {};
- /*! @copydoc is_iterator_type */
- template<typename Type, typename It>
- struct is_iterator_type<Type, It, std::enable_if_t<is_iterator_v<Type> && std::is_same_v<Type, It>>>
- : std::true_type
- {};
- /*! @copydoc is_iterator_type */
- template<typename Type, typename It>
- struct is_iterator_type<Type, It, std::enable_if_t<!std::is_same_v<Type, It>, std::void_t<typename It::iterator_type>>>
- : is_iterator_type<Type, typename It::iterator_type>
- {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- * @tparam It Required iterator type.
- */
- template<typename Type, typename It>
- inline constexpr bool is_iterator_type_v = is_iterator_type<Type, It>::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;
- }
- #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 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;
- };
- }
- #endif
- // #include "entity/component.hpp"
- #ifndef ENTT_ENTITY_COMPONENT_HPP
- #define ENTT_ENTITY_COMPONENT_HPP
- #include <type_traits>
- // #include "../config/config.h"
- #ifndef ENTT_CONFIG_CONFIG_H
- #define ENTT_CONFIG_CONFIG_H
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_NOEXCEPT noexcept
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_NOEXCEPT
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606L
- # include <new>
- # define ENTT_LAUNDER(expr) std::launder(expr)
- #else
- # define ENTT_LAUNDER(expr) expr
- #endif
- #ifndef ENTT_USE_ATOMIC
- # define ENTT_MAYBE_ATOMIC(Type) Type
- #else
- # include <atomic>
- # define ENTT_MAYBE_ATOMIC(Type) std::atomic<Type>
- #endif
- #ifndef ENTT_ID_TYPE
- # include <cstdint>
- # define ENTT_ID_TYPE std::uint32_t
- #endif
- #ifdef ENTT_SPARSE_PAGE
- static_assert(ENTT_SPARSE_PAGE && ((ENTT_SPARSE_PAGE & (ENTT_SPARSE_PAGE - 1)) == 0), "ENTT_SPARSE_PAGE must be a power of two");
- #else
- # define ENTT_SPARSE_PAGE 4096
- #endif
- #ifdef ENTT_PACKED_PAGE
- static_assert(ENTT_PACKED_PAGE && ((ENTT_PACKED_PAGE & (ENTT_PACKED_PAGE - 1)) == 0), "ENTT_PACKED_PAGE must be a power of two");
- #else
- # 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
- # include <type_traits>
- # define ENTT_IGNORE_IF_EMPTY std::false_type
- #else
- # include <type_traits>
- # define ENTT_IGNORE_IF_EMPTY std::true_type
- #endif
- #ifndef ENTT_STANDARD_CPP
- # 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
- #endif
- namespace entt {
- /*! @brief Commonly used default traits for all types. */
- struct basic_component_traits {
- /*! @brief Pointer stability, default is `std::false_type`. */
- using in_place_delete = std::false_type;
- /*! @brief Empty type optimization, default is `ENTT_IGNORE_IF_EMPTY`. */
- using ignore_if_empty = ENTT_IGNORE_IF_EMPTY;
- };
- /**
- * @brief Common way to access various properties of components.
- * @tparam Type Type of component.
- */
- template<typename Type, typename = void>
- struct component_traits: basic_component_traits {
- static_assert(std::is_same_v<std::decay_t<Type>, Type>, "Unsupported type");
- };
- }
- #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"
- 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;
- using difference_type = std::int64_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;
- using difference_type = std::int64_t;
- static constexpr entity_type entity_mask = 0xFFFFFFFF;
- static constexpr entity_type version_mask = 0xFFFFFFFF;
- static constexpr std::size_t entity_shift = 32u;
- };
- }
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /**
- * @brief Entity traits.
- * @tparam Type Type of identifier.
- */
- template<typename Type>
- class entt_traits: private internal::entt_traits<Type> {
- using traits_type = internal::entt_traits<Type>;
- public:
- /*! @brief Value type. */
- using value_type = Type;
- /*! @brief Underlying entity type. */
- using entity_type = typename traits_type::entity_type;
- /*! @brief Underlying version type. */
- using version_type = typename traits_type::version_type;
- /*! @brief Difference type. */
- using difference_type = typename traits_type::difference_type;
- /**
- * @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) & traits_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 {
- constexpr auto mask = (traits_type::version_mask << traits_type::entity_shift);
- return ((to_integral(value) & mask) >> traits_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 = traits_type::entity_mask, const version_type version = traits_type::version_mask) ENTT_NOEXCEPT {
- return value_type{(entity & traits_type::entity_mask) | (version << traits_type::entity_shift)};
- }
- };
- /**
- * @brief Converts an entity to its underlying type.
- * @tparam Entity The value type.
- * @param entity The value to convert.
- * @return The integral representation of the given value.
- */
- template<typename Entity>
- [[nodiscard]] constexpr auto to_integral(const Entity entity) ENTT_NOEXCEPT {
- return entt_traits<Entity>::to_integral(entity);
- }
- /*! @brief Null object for all entity identifiers. */
- struct null_t {
- /**
- * @brief Converts the null object to identifiers of any type.
- * @tparam Entity Type of entity identifier.
- * @return The null representation for the given type.
- */
- template<typename Entity>
- [[nodiscard]] constexpr operator Entity() const ENTT_NOEXCEPT {
- return entt_traits<Entity>::construct();
- }
- /**
- * @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 entity identifier of any type.
- * @tparam Entity Type of entity identifier.
- * @param entity 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 {
- return entt_traits<Entity>::to_entity(entity) == entt_traits<Entity>::to_entity(*this);
- }
- /**
- * @brief Compares a null object and an entity identifier of any type.
- * @tparam Entity Type of entity identifier.
- * @param entity 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 Creates a null object from an entity identifier of any type.
- * @tparam Entity Type of entity identifier.
- * @param entity Entity identifier to turn into a null object.
- * @return The null representation for the given identifier.
- */
- template<typename Entity>
- [[nodiscard]] constexpr Entity operator|(const Entity entity) const ENTT_NOEXCEPT {
- return entt_traits<Entity>::construct(entt_traits<Entity>::to_entity(*this), entt_traits<Entity>::to_version(entity));
- }
- };
- /**
- * @brief Compares a null object and an entity identifier of any type.
- * @tparam Entity Type of entity identifier.
- * @param entity 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 entity identifier of any type.
- * @tparam Entity Type of entity identifier.
- * @param entity 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 entity identifiers. */
- struct tombstone_t {
- /**
- * @brief Converts the tombstone object to identifiers of any type.
- * @tparam Entity Type of entity identifier.
- * @return The tombstone representation for the given type.
- */
- template<typename Entity>
- [[nodiscard]] constexpr operator Entity() const ENTT_NOEXCEPT {
- return entt_traits<Entity>::construct();
- }
- /**
- * @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 entity identifier of any type.
- * @tparam Entity Type of entity identifier.
- * @param entity 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 {
- return entt_traits<Entity>::to_version(entity) == entt_traits<Entity>::to_version(*this);
- }
- /**
- * @brief Compares a tombstone object and an entity identifier of any type.
- * @tparam Entity Type of entity identifier.
- * @param entity 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 Creates a tombstone object from an entity identifier of any type.
- * @tparam Entity Type of entity identifier.
- * @param entity Entity identifier to turn into a tombstone object.
- * @return The tombstone representation for the given identifier.
- */
- template<typename Entity>
- [[nodiscard]] constexpr Entity operator|(const Entity entity) const ENTT_NOEXCEPT {
- return entt_traits<Entity>::construct(entt_traits<Entity>::to_entity(entity));
- }
- };
- /**
- * @brief Compares a tombstone object and an entity identifier of any type.
- * @tparam Entity Type of entity identifier.
- * @param entity 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 entity identifier of any type.
- * @tparam Entity Type of entity identifier.
- * @param entity 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 entity identifiers of
- * any allowed type. Similarly, there exist comparision operators between the
- * null entity and any other entity identifier.
- */
- inline constexpr null_t null{};
- /**
- * @brief Compile-time constant for tombstone entities.
- *
- * There exist implicit conversions from this variable to entity identifiers of
- * any allowed type. Similarly, there exist comparision operators between the
- * tombstone entity and any other entity identifier.
- */
- inline constexpr tombstone_t tombstone{};
- }
- #endif
- // #include "entity/group.hpp"
- #ifndef ENTT_ENTITY_GROUP_HPP
- #define ENTT_ENTITY_GROUP_HPP
- #include <tuple>
- #include <utility>
- #include <type_traits>
- // #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
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_NOEXCEPT noexcept
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_NOEXCEPT
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606L
- # include <new>
- # define ENTT_LAUNDER(expr) std::launder(expr)
- #else
- # define ENTT_LAUNDER(expr) expr
- #endif
- #ifndef ENTT_USE_ATOMIC
- # define ENTT_MAYBE_ATOMIC(Type) Type
- #else
- # include <atomic>
- # define ENTT_MAYBE_ATOMIC(Type) std::atomic<Type>
- #endif
- #ifndef ENTT_ID_TYPE
- # include <cstdint>
- # define ENTT_ID_TYPE std::uint32_t
- #endif
- #ifdef ENTT_SPARSE_PAGE
- static_assert(ENTT_SPARSE_PAGE && ((ENTT_SPARSE_PAGE & (ENTT_SPARSE_PAGE - 1)) == 0), "ENTT_SPARSE_PAGE must be a power of two");
- #else
- # define ENTT_SPARSE_PAGE 4096
- #endif
- #ifdef ENTT_PACKED_PAGE
- static_assert(ENTT_PACKED_PAGE && ((ENTT_PACKED_PAGE & (ENTT_PACKED_PAGE - 1)) == 0), "ENTT_PACKED_PAGE must be a power of two");
- #else
- # 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
- # include <type_traits>
- # define ENTT_IGNORE_IF_EMPTY std::false_type
- #else
- # include <type_traits>
- # define ENTT_IGNORE_IF_EMPTY std::true_type
- #endif
- #ifndef ENTT_STANDARD_CPP
- # 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
- #endif
- // #include "fwd.hpp"
- #ifndef ENTT_CORE_FWD_HPP
- #define ENTT_CORE_FWD_HPP
- #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<>;
- }
- #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<class 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_t = 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_v = 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::disjunction_v<std::is_same<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<class 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;
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- namespace internal {
- template<typename>
- [[nodiscard]] constexpr bool is_equality_comparable(...) { return false; }
- template<typename Type>
- [[nodiscard]] constexpr auto is_equality_comparable(choice_t<0>)
- -> decltype(std::declval<Type>() == std::declval<Type>()) { return true; }
- template<typename Type>
- [[nodiscard]] constexpr auto is_equality_comparable(choice_t<1>)
- -> decltype(std::declval<typename Type::value_type>(), std::declval<Type>() == std::declval<Type>()) {
- if constexpr(std::is_same_v<typename Type::value_type, Type>) {
- return is_equality_comparable<Type>(choice<0>);
- } else {
- return is_equality_comparable<typename Type::value_type>(choice<2>);
- }
- }
- template<typename Type>
- [[nodiscard]] constexpr auto is_equality_comparable(choice_t<2>)
- -> decltype(std::declval<typename Type::mapped_type>(), std::declval<Type>() == std::declval<Type>()) {
- return is_equality_comparable<typename Type::key_type>(choice<2>) && is_equality_comparable<typename Type::mapped_type>(choice<2>);
- }
- }
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /**
- * @brief Provides the member constant `value` to true if a given type is
- * equality comparable, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_equality_comparable: std::bool_constant<internal::is_equality_comparable<Type>(choice<2>)> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<class Type>
- inline constexpr bool is_equality_comparable_v = is_equality_comparable<Type>::value;
- /*! @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 {};
- /*! @copydoc is_iterator */
- template<typename Type>
- struct is_iterator<Type, std::void_t<typename std::iterator_traits<Type>::iterator_category>>
- : std::true_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 of the
- * required iterator type, false otherwise.
- * @tparam Type The type to test.
- * @tparam It Required iterator type.
- */
- template<typename Type, typename It, typename = void>
- struct is_iterator_type: std::false_type {};
- /*! @copydoc is_iterator_type */
- template<typename Type, typename It>
- struct is_iterator_type<Type, It, std::enable_if_t<is_iterator_v<Type> && std::is_same_v<Type, It>>>
- : std::true_type
- {};
- /*! @copydoc is_iterator_type */
- template<typename Type, typename It>
- struct is_iterator_type<Type, It, std::enable_if_t<!std::is_same_v<Type, It>, std::void_t<typename It::iterator_type>>>
- : is_iterator_type<Type, typename It::iterator_type>
- {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- * @tparam It Required iterator type.
- */
- template<typename Type, typename It>
- inline constexpr bool is_iterator_type_v = is_iterator_type<Type, It>::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;
- }
- #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"
- 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;
- using difference_type = std::int64_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;
- using difference_type = std::int64_t;
- static constexpr entity_type entity_mask = 0xFFFFFFFF;
- static constexpr entity_type version_mask = 0xFFFFFFFF;
- static constexpr std::size_t entity_shift = 32u;
- };
- }
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /**
- * @brief Entity traits.
- * @tparam Type Type of identifier.
- */
- template<typename Type>
- class entt_traits: private internal::entt_traits<Type> {
- using traits_type = internal::entt_traits<Type>;
- public:
- /*! @brief Value type. */
- using value_type = Type;
- /*! @brief Underlying entity type. */
- using entity_type = typename traits_type::entity_type;
- /*! @brief Underlying version type. */
- using version_type = typename traits_type::version_type;
- /*! @brief Difference type. */
- using difference_type = typename traits_type::difference_type;
- /**
- * @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) & traits_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 {
- constexpr auto mask = (traits_type::version_mask << traits_type::entity_shift);
- return ((to_integral(value) & mask) >> traits_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 = traits_type::entity_mask, const version_type version = traits_type::version_mask) ENTT_NOEXCEPT {
- return value_type{(entity & traits_type::entity_mask) | (version << traits_type::entity_shift)};
- }
- };
- /**
- * @brief Converts an entity to its underlying type.
- * @tparam Entity The value type.
- * @param entity The value to convert.
- * @return The integral representation of the given value.
- */
- template<typename Entity>
- [[nodiscard]] constexpr auto to_integral(const Entity entity) ENTT_NOEXCEPT {
- return entt_traits<Entity>::to_integral(entity);
- }
- /*! @brief Null object for all entity identifiers. */
- struct null_t {
- /**
- * @brief Converts the null object to identifiers of any type.
- * @tparam Entity Type of entity identifier.
- * @return The null representation for the given type.
- */
- template<typename Entity>
- [[nodiscard]] constexpr operator Entity() const ENTT_NOEXCEPT {
- return entt_traits<Entity>::construct();
- }
- /**
- * @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 entity identifier of any type.
- * @tparam Entity Type of entity identifier.
- * @param entity 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 {
- return entt_traits<Entity>::to_entity(entity) == entt_traits<Entity>::to_entity(*this);
- }
- /**
- * @brief Compares a null object and an entity identifier of any type.
- * @tparam Entity Type of entity identifier.
- * @param entity 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 Creates a null object from an entity identifier of any type.
- * @tparam Entity Type of entity identifier.
- * @param entity Entity identifier to turn into a null object.
- * @return The null representation for the given identifier.
- */
- template<typename Entity>
- [[nodiscard]] constexpr Entity operator|(const Entity entity) const ENTT_NOEXCEPT {
- return entt_traits<Entity>::construct(entt_traits<Entity>::to_entity(*this), entt_traits<Entity>::to_version(entity));
- }
- };
- /**
- * @brief Compares a null object and an entity identifier of any type.
- * @tparam Entity Type of entity identifier.
- * @param entity 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 entity identifier of any type.
- * @tparam Entity Type of entity identifier.
- * @param entity 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 entity identifiers. */
- struct tombstone_t {
- /**
- * @brief Converts the tombstone object to identifiers of any type.
- * @tparam Entity Type of entity identifier.
- * @return The tombstone representation for the given type.
- */
- template<typename Entity>
- [[nodiscard]] constexpr operator Entity() const ENTT_NOEXCEPT {
- return entt_traits<Entity>::construct();
- }
- /**
- * @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 entity identifier of any type.
- * @tparam Entity Type of entity identifier.
- * @param entity 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 {
- return entt_traits<Entity>::to_version(entity) == entt_traits<Entity>::to_version(*this);
- }
- /**
- * @brief Compares a tombstone object and an entity identifier of any type.
- * @tparam Entity Type of entity identifier.
- * @param entity 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 Creates a tombstone object from an entity identifier of any type.
- * @tparam Entity Type of entity identifier.
- * @param entity Entity identifier to turn into a tombstone object.
- * @return The tombstone representation for the given identifier.
- */
- template<typename Entity>
- [[nodiscard]] constexpr Entity operator|(const Entity entity) const ENTT_NOEXCEPT {
- return entt_traits<Entity>::construct(entt_traits<Entity>::to_entity(entity));
- }
- };
- /**
- * @brief Compares a tombstone object and an entity identifier of any type.
- * @tparam Entity Type of entity identifier.
- * @param entity 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 entity identifier of any type.
- * @tparam Entity Type of entity identifier.
- * @param entity 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 entity identifiers of
- * any allowed type. Similarly, there exist comparision operators between the
- * null entity and any other entity identifier.
- */
- inline constexpr null_t null{};
- /**
- * @brief Compile-time constant for tombstone entities.
- *
- * There exist implicit conversions from this variable to entity identifiers of
- * any allowed type. Similarly, there exist comparision operators between the
- * tombstone entity and any other entity identifier.
- */
- inline constexpr tombstone_t tombstone{};
- }
- #endif
- // #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 <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<>;
- }
- #endif
- namespace entt {
- template<typename Entity, typename = std::allocator<Entity>>
- class basic_sparse_set;
- template<typename, typename Type, typename = std::allocator<Type>>
- struct basic_storage;
- template<typename>
- class basic_registry;
- template<typename...>
- struct basic_view;
- template<typename>
- class basic_runtime_view;
- template<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 Args Other template parameters.
- */
- template<typename... Args>
- using view = basic_view<entity, Args...>;
- /*! @brief Alias declaration for the most common use case. */
- using runtime_view = basic_runtime_view<entity>;
- /**
- * @brief Alias declaration for the most common use case.
- * @tparam Args Other template parameters.
- */
- template<typename... Args>
- using group = basic_group<entity, Args...>;
- }
- #endif
- // #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 "../config/config.h"
- // #include "../core/algorithm.hpp"
- #ifndef ENTT_CORE_ALGORITHM_HPP
- #define ENTT_CORE_ALGORITHM_HPP
- #include <vector>
- #include <utility>
- #include <iterator>
- #include <algorithm>
- #include <functional>
- // #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 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;
- };
- }
- #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);
- }
- }
- }
- };
- }
- #endif
- // #include "../core/fwd.hpp"
- // #include "entity.hpp"
- // #include "fwd.hpp"
- namespace entt {
- /*! @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 {
- static constexpr auto growth_factor = 1.5;
- static constexpr auto sparse_page = ENTT_SPARSE_PAGE;
- using traits_type = entt_traits<Entity>;
- using alloc_traits = typename std::allocator_traits<Allocator>::template rebind_traits<Entity>;
- using alloc_pointer = typename alloc_traits::pointer;
- using alloc_const_pointer = typename alloc_traits::const_pointer;
- using bucket_alloc_traits = typename std::allocator_traits<Allocator>::template rebind_traits<alloc_pointer>;
- using bucket_alloc_pointer = typename bucket_alloc_traits::pointer;
- static_assert(alloc_traits::propagate_on_container_move_assignment::value);
- static_assert(bucket_alloc_traits::propagate_on_container_move_assignment::value);
- struct sparse_set_iterator final {
- using difference_type = typename traits_type::difference_type;
- using value_type = Entity;
- using pointer = const value_type *;
- using reference = const value_type &;
- using iterator_category = std::random_access_iterator_tag;
- sparse_set_iterator() ENTT_NOEXCEPT = default;
- sparse_set_iterator(const alloc_const_pointer *ref, const difference_type idx) ENTT_NOEXCEPT
- : packed{ref},
- index{idx}
- {}
- sparse_set_iterator & operator++() ENTT_NOEXCEPT {
- return --index, *this;
- }
- sparse_set_iterator operator++(int) ENTT_NOEXCEPT {
- iterator orig = *this;
- return ++(*this), orig;
- }
- sparse_set_iterator & operator--() ENTT_NOEXCEPT {
- return ++index, *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 {
- index -= 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);
- }
- difference_type operator-(const sparse_set_iterator &other) const ENTT_NOEXCEPT {
- return other.index - index;
- }
- [[nodiscard]] reference operator[](const difference_type value) const {
- const auto pos = size_type(index-value-1u);
- return (*packed)[pos];
- }
- [[nodiscard]] bool operator==(const sparse_set_iterator &other) const ENTT_NOEXCEPT {
- return other.index == index;
- }
- [[nodiscard]] bool operator!=(const sparse_set_iterator &other) const ENTT_NOEXCEPT {
- return !(*this == other);
- }
- [[nodiscard]] bool operator<(const sparse_set_iterator &other) const ENTT_NOEXCEPT {
- return index > other.index;
- }
- [[nodiscard]] bool operator>(const sparse_set_iterator &other) const ENTT_NOEXCEPT {
- return index < other.index;
- }
- [[nodiscard]] bool operator<=(const sparse_set_iterator &other) const ENTT_NOEXCEPT {
- return !(*this > other);
- }
- [[nodiscard]] bool operator>=(const sparse_set_iterator &other) const ENTT_NOEXCEPT {
- return !(*this < other);
- }
- [[nodiscard]] pointer operator->() const {
- const auto pos = size_type(index-1u);
- return std::addressof((*packed)[pos]);
- }
- [[nodiscard]] reference operator*() const {
- return *operator->();
- }
- private:
- const alloc_const_pointer *packed;
- difference_type index;
- };
- [[nodiscard]] static auto page(const Entity entt) ENTT_NOEXCEPT {
- return size_type{traits_type::to_entity(entt) / sparse_page};
- }
- [[nodiscard]] static auto offset(const Entity entt) ENTT_NOEXCEPT {
- return size_type{traits_type::to_entity(entt) & (sparse_page - 1)};
- }
- [[nodiscard]] auto assure_page(const std::size_t idx) {
- if(!(idx < bucket)) {
- const size_type sz = idx + 1u;
- const auto mem = bucket_alloc_traits::allocate(bucket_allocator, sz);
- std::uninitialized_value_construct(mem + bucket, mem + sz);
- std::uninitialized_copy(sparse, sparse + bucket, mem);
- std::destroy(sparse, sparse + bucket);
- bucket_alloc_traits::deallocate(bucket_allocator, sparse, bucket);
- sparse = mem;
- bucket = sz;
- }
- if(!sparse[idx]) {
- sparse[idx] = alloc_traits::allocate(allocator, sparse_page);
- std::uninitialized_fill(sparse[idx], sparse[idx] + sparse_page, null);
- }
- return sparse[idx];
- }
- void resize_packed(const std::size_t req) {
- ENTT_ASSERT((req != reserved) && !(req < count), "Invalid request");
- const auto mem = alloc_traits::allocate(allocator, req);
- std::uninitialized_copy(packed, packed + count, mem);
- std::uninitialized_fill(mem + count, mem + req, tombstone);
- std::destroy(packed, packed + reserved);
- alloc_traits::deallocate(allocator, packed, reserved);
- packed = mem;
- reserved = req;
- }
- void release_memory() {
- if(packed) {
- for(size_type pos{}; pos < bucket; ++pos) {
- if(sparse[pos]) {
- std::destroy(sparse[pos], sparse[pos] + sparse_page);
- alloc_traits::deallocate(allocator, sparse[pos], sparse_page);
- }
- }
- std::destroy(packed, packed + reserved);
- std::destroy(sparse, sparse + bucket);
- alloc_traits::deallocate(allocator, packed, reserved);
- bucket_alloc_traits::deallocate(bucket_allocator, sparse, bucket);
- }
- }
- protected:
- /**
- * @brief Swaps two entities in the internal packed array.
- * @param lhs A valid position of an entity within storage.
- * @param rhs A valid position of an entity within storage.
- */
- virtual void swap_at([[maybe_unused]] const std::size_t lhs, [[maybe_unused]] const std::size_t rhs) {}
- /**
- * @brief Moves an entity in the internal packed array.
- * @param from A valid position of an entity within storage.
- * @param to A valid position of an entity within storage.
- */
- virtual void move_and_pop([[maybe_unused]] const std::size_t from, [[maybe_unused]] const std::size_t to) {}
- /**
- * @brief Attempts to erase an entity from the internal packed array.
- * @param entt A valid entity identifier.
- * @param ud Optional user data that are forwarded as-is to derived classes.
- */
- virtual void swap_and_pop(const Entity entt, [[maybe_unused]] void *ud) {
- auto &ref = sparse[page(entt)][offset(entt)];
- const auto pos = size_type{traits_type::to_entity(ref)};
- ENTT_ASSERT(packed[pos] == entt, "Invalid entity identifier");
- auto &last = packed[--count];
- packed[pos] = last;
- sparse[page(last)][offset(last)] = ref;
- // lazy self-assignment guard
- ref = null;
- // unnecessary but it helps to detect nasty bugs
- ENTT_ASSERT((last = tombstone, true), "");
- }
- /**
- * @brief Attempts to erase an entity from the internal packed array.
- * @param entt A valid entity identifier.
- * @param ud Optional user data that are forwarded as-is to derived classes.
- */
- virtual void in_place_pop(const Entity entt, [[maybe_unused]] void *ud) {
- auto &ref = sparse[page(entt)][offset(entt)];
- const auto pos = size_type{traits_type::to_entity(ref)};
- ENTT_ASSERT(packed[pos] == entt, "Invalid entity identifier");
- packed[pos] = std::exchange(free_list, traits_type::construct(static_cast<typename traits_type::entity_type>(pos)));
- // lazy self-assignment guard
- ref = null;
- }
- public:
- /*! @brief Allocator type. */
- using allocator_type = typename alloc_traits::allocator_type;
- /*! @brief Underlying entity identifier. */
- using entity_type = Entity;
- /*! @brief Unsigned integer type. */
- using size_type = std::size_t;
- /*! @brief Pointer type to contained entities. */
- using pointer = alloc_const_pointer;
- /*! @brief Random access iterator type. */
- using iterator = sparse_set_iterator;
- /*! @brief Reverse iterator type. */
- using reverse_iterator = std::reverse_iterator<iterator>;
- /**
- * @brief Constructs an empty container with the given policy and allocator.
- * @param pol Type of deletion policy.
- * @param alloc Allocator to use (possibly default-constructed).
- */
- explicit basic_sparse_set(deletion_policy pol, const allocator_type &alloc = {})
- : allocator{alloc},
- bucket_allocator{alloc},
- sparse{bucket_alloc_traits::allocate(bucket_allocator, 0u)},
- packed{alloc_traits::allocate(allocator, 0u)},
- bucket{0u},
- count{0u},
- reserved{0u},
- free_list{tombstone},
- mode{pol}
- {}
- /**
- * @brief Constructs an empty container with the given allocator.
- * @param alloc Allocator to use (possibly default-constructed).
- */
- explicit basic_sparse_set(const allocator_type &alloc = {})
- : basic_sparse_set{deletion_policy::swap_and_pop, alloc}
- {}
- /**
- * @brief Move constructor.
- * @param other The instance to move from.
- */
- basic_sparse_set(basic_sparse_set &&other) ENTT_NOEXCEPT
- : allocator{std::move(other.allocator)},
- bucket_allocator{std::move(other.bucket_allocator)},
- sparse{std::exchange(other.sparse, bucket_alloc_pointer{})},
- packed{std::exchange(other.packed, alloc_pointer{})},
- bucket{std::exchange(other.bucket, 0u)},
- count{std::exchange(other.count, 0u)},
- reserved{std::exchange(other.reserved, 0u)},
- free_list{std::exchange(other.free_list, tombstone)},
- mode{other.mode}
- {}
- /*! @brief Default destructor. */
- virtual ~basic_sparse_set() {
- release_memory();
- }
- /**
- * @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 {
- release_memory();
- allocator = std::move(other.allocator);
- bucket_allocator = std::move(other.bucket_allocator);
- sparse = std::exchange(other.sparse, bucket_alloc_pointer{});
- packed = std::exchange(other.packed, alloc_pointer{});
- bucket = std::exchange(other.bucket, 0u);
- count = std::exchange(other.count, 0u);
- reserved = std::exchange(other.reserved, 0u);
- free_list = std::exchange(other.free_list, tombstone);
- mode = other.mode;
- return *this;
- }
- /**
- * @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 Returns the next slot available for insertion.
- * @return The next slot available for insertion.
- */
- [[nodiscard]] size_type slot() const ENTT_NOEXCEPT {
- return free_list == null ? count : size_type{traits_type::to_entity(free_list)};
- }
- /**
- * @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.
- */
- void reserve(const size_type cap) {
- if(cap > reserved) {
- resize_packed(cap);
- }
- }
- /**
- * @brief Returns the number of elements that a sparse set has currently
- * allocated space for.
- * @return Capacity of the sparse set.
- */
- [[nodiscard]] size_type capacity() const ENTT_NOEXCEPT {
- return reserved;
- }
- /*! @brief Requests the removal of unused capacity. */
- void shrink_to_fit() {
- if(count < reserved) {
- resize_packed(count);
- }
- }
- /**
- * @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 bucket * sparse_page;
- }
- /**
- * @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 count;
- }
- /**
- * @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 (count == size_type{});
- }
- /**
- * @brief Direct access to the internal packed array.
- * @return A pointer to the internal packed array.
- */
- [[nodiscard]] pointer data() const ENTT_NOEXCEPT {
- return packed;
- }
- /**
- * @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 internal packed array.
- */
- [[nodiscard]] iterator begin() const ENTT_NOEXCEPT {
- return iterator{std::addressof(packed), static_cast<typename traits_type::difference_type>(count)};
- }
- /**
- * @brief Returns an iterator to the end.
- *
- * The returned iterator points to the element following the last entity in
- * the internal packed array. Attempting to dereference the returned
- * iterator results in undefined behavior.
- *
- * @return An iterator to the element following the last entity of the
- * internal packed array.
- */
- [[nodiscard]] iterator end() const ENTT_NOEXCEPT {
- return iterator{std::addressof(packed), {}};
- }
- /**
- * @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]] reverse_iterator rbegin() const 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 entity in
- * the reversed internal packed array. Attempting to dereference the
- * returned iterator results in undefined behavior.
- *
- * @return An iterator to the element following the last entity of the
- * reversed internal packed array.
- */
- [[nodiscard]] reverse_iterator rend() const ENTT_NOEXCEPT {
- return std::make_reverse_iterator(begin());
- }
- /**
- * @brief Finds an entity.
- * @param entt A valid entity 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 entity identifier.
- * @return True if the sparse set contains the entity, false otherwise.
- */
- [[nodiscard]] bool contains(const entity_type entt) const ENTT_NOEXCEPT {
- ENTT_ASSERT(entt != tombstone && entt != null, "Invalid entity");
- const auto curr = page(entt);
- // testing versions permits to avoid accessing the packed array
- return (curr < bucket && sparse[curr] && sparse[curr][offset(entt)] != null);
- }
- /**
- * @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 entity 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 size_type{traits_type::to_entity(sparse[page(entt)][offset(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 < count ? 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 < count, "Position is out of bounds");
- return packed[pos];
- }
- /**
- * @brief Appends 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 entity identifier.
- * @return The slot used for insertion.
- */
- size_type emplace_back(const entity_type entt) {
- ENTT_ASSERT(!contains(entt), "Set already contains entity");
- if(count == reserved) {
- const size_type sz = static_cast<size_type>(reserved * growth_factor);
- resize_packed(sz + !(sz > reserved));
- }
- assure_page(page(entt))[offset(entt)] = traits_type::construct(static_cast<typename traits_type::entity_type>(count));
- packed[count] = entt;
- return count++;
- }
- /**
- * @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 entity identifier.
- * @return The slot used for insertion.
- */
- size_type emplace(const entity_type entt) {
- if(free_list == null) {
- return emplace_back(entt);
- } else {
- ENTT_ASSERT(!contains(entt), "Set already contains entity");
- const auto pos = size_type{traits_type::to_entity(free_list)};
- sparse[page(entt)][offset(entt)] = traits_type::construct(static_cast<typename traits_type::entity_type>(pos));
- free_list = std::exchange(packed[pos], entt);
- return pos;
- }
- }
- /**
- * @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.
- */
- template<typename It>
- void insert(It first, It last) {
- reserve(count + std::distance(first, last));
- for(; first != last; ++first) {
- const auto entt = *first;
- ENTT_ASSERT(!contains(entt), "Set already contains entity");
- assure_page(page(entt))[offset(entt)] = traits_type::construct(static_cast<typename traits_type::entity_type>(count));
- packed[count++] = entt;
- }
- }
- /**
- * @brief Erases an entity from a sparse set.
- *
- * @warning
- * Attempting to erase an entity that doesn't belong to the sparse set
- * results in undefined behavior.
- *
- * @param entt A valid entity identifier.
- * @param ud Optional user data that are forwarded as-is to derived classes.
- */
- void erase(const entity_type entt, void *ud = nullptr) {
- ENTT_ASSERT(contains(entt), "Set does not contain entity");
- (mode == deletion_policy::in_place) ? in_place_pop(entt, ud) : swap_and_pop(entt, ud);
- }
- /**
- * @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.
- * @param ud Optional user data that are forwarded as-is to derived classes.
- */
- template<typename It>
- void erase(It first, It last, void *ud = nullptr) {
- for(; first != last; ++first) {
- erase(*first, ud);
- }
- }
- /**
- * @brief Removes an entity from a sparse set if it exists.
- * @param entt A valid entity identifier.
- * @param ud Optional user data that are forwarded as-is to derived classes.
- * @return True if the entity is actually removed, false otherwise.
- */
- bool remove(const entity_type entt, void *ud = nullptr) {
- return contains(entt) && (erase(entt, ud), 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.
- * @param ud Optional user data that are forwarded as-is to derived classes.
- * @return The number of entities actually removed.
- */
- template<typename It>
- size_type remove(It first, It last, void *ud = nullptr) {
- size_type found{};
- for(; first != last; ++first) {
- found += remove(*first, ud);
- }
- return found;
- }
- /*! @brief Removes all tombstones from the packed array of a sparse set. */
- void compact() {
- size_type next = count;
- for(; next && packed[next - 1u] == tombstone; --next);
- for(auto *it = &free_list; *it != null && next; it = std::addressof(packed[traits_type::to_entity(*it)])) {
- if(const size_type pos = traits_type::to_entity(*it); pos < next) {
- --next;
- move_and_pop(next, pos);
- std::swap(packed[next], packed[pos]);
- sparse[page(packed[pos])][offset(packed[pos])] = traits_type::construct(static_cast<const typename traits_type::entity_type>(pos));
- *it = traits_type::construct(static_cast<typename traits_type::entity_type>(next));
- for(; next && packed[next - 1u] == tombstone; --next);
- }
- }
- free_list = tombstone;
- count = next;
- }
- /**
- * @copybrief swap_at
- *
- * 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 entity identifier.
- * @param rhs A valid entity identifier.
- */
- void swap(const entity_type lhs, const entity_type rhs) {
- ENTT_ASSERT(contains(lhs), "Set does not contain entity");
- ENTT_ASSERT(contains(rhs), "Set does not contain entity");
- auto &entt = sparse[page(lhs)][offset(lhs)];
- auto &other = sparse[page(rhs)][offset(rhs)];
- const auto from = size_type{traits_type::to_entity(entt)};
- const auto to = size_type{traits_type::to_entity(other)};
- // basic no-leak guarantee (with invalid state) if swapping throws
- swap_at(from, to);
- std::swap(entt, other);
- std::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) {
- // basic no-leak guarantee (with invalid state) if sorting throws
- ENTT_ASSERT(!(length > count), "Length exceeds the number of elements");
- compact();
- algo(std::make_reverse_iterator(packed + length), std::make_reverse_iterator(packed), 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);
- sparse[page(entt)][offset(entt)] = traits_type::construct(static_cast<typename traits_type::entity_type>(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) {
- sort_n(count, 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 = count - 1; pos && from != to; ++from) {
- if(contains(*from)) {
- if(*from != packed[pos]) {
- // basic no-leak guarantee (with invalid state) if swapping throws
- swap(packed[pos], *from);
- }
- --pos;
- }
- }
- }
- /**
- * @brief Clears a sparse set.
- * @param ud Optional user data that are forwarded as-is to derived classes.
- */
- void clear(void *ud = nullptr) {
- for(auto &&entity: *this) {
- if(entity != tombstone) {
- in_place_pop(entity, ud);
- }
- }
- free_list = tombstone;
- count = 0u;
- }
- private:
- typename alloc_traits::allocator_type allocator;
- typename bucket_alloc_traits::allocator_type bucket_allocator;
- bucket_alloc_pointer sparse;
- alloc_pointer packed;
- std::size_t bucket;
- std::size_t count;
- std::size_t reserved;
- entity_type free_list;
- deletion_policy mode;
- };
- }
- #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 "../config/config.h"
- // #include "../core/algorithm.hpp"
- // #include "../core/fwd.hpp"
- // #include "../core/type_traits.hpp"
- // #include "../signal/sigh.hpp"
- #ifndef ENTT_SIGNAL_SIGH_HPP
- #define ENTT_SIGNAL_SIGH_HPP
- #include <vector>
- #include <utility>
- #include <iterator>
- #include <algorithm>
- #include <functional>
- #include <type_traits>
- // #include "../config/config.h"
- #ifndef ENTT_CONFIG_CONFIG_H
- #define ENTT_CONFIG_CONFIG_H
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_NOEXCEPT noexcept
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_NOEXCEPT
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606L
- # include <new>
- # define ENTT_LAUNDER(expr) std::launder(expr)
- #else
- # define ENTT_LAUNDER(expr) expr
- #endif
- #ifndef ENTT_USE_ATOMIC
- # define ENTT_MAYBE_ATOMIC(Type) Type
- #else
- # include <atomic>
- # define ENTT_MAYBE_ATOMIC(Type) std::atomic<Type>
- #endif
- #ifndef ENTT_ID_TYPE
- # include <cstdint>
- # define ENTT_ID_TYPE std::uint32_t
- #endif
- #ifdef ENTT_SPARSE_PAGE
- static_assert(ENTT_SPARSE_PAGE && ((ENTT_SPARSE_PAGE & (ENTT_SPARSE_PAGE - 1)) == 0), "ENTT_SPARSE_PAGE must be a power of two");
- #else
- # define ENTT_SPARSE_PAGE 4096
- #endif
- #ifdef ENTT_PACKED_PAGE
- static_assert(ENTT_PACKED_PAGE && ((ENTT_PACKED_PAGE & (ENTT_PACKED_PAGE - 1)) == 0), "ENTT_PACKED_PAGE must be a power of two");
- #else
- # 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
- # include <type_traits>
- # define ENTT_IGNORE_IF_EMPTY std::false_type
- #else
- # include <type_traits>
- # define ENTT_IGNORE_IF_EMPTY std::true_type
- #endif
- #ifndef ENTT_STANDARD_CPP
- # 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
- #endif
- // #include "delegate.hpp"
- #ifndef ENTT_SIGNAL_DELEGATE_HPP
- #define ENTT_SIGNAL_DELEGATE_HPP
- #include <tuple>
- #include <cstddef>
- #include <utility>
- #include <functional>
- #include <type_traits>
- // #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
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_NOEXCEPT noexcept
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_NOEXCEPT
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606L
- # include <new>
- # define ENTT_LAUNDER(expr) std::launder(expr)
- #else
- # define ENTT_LAUNDER(expr) expr
- #endif
- #ifndef ENTT_USE_ATOMIC
- # define ENTT_MAYBE_ATOMIC(Type) Type
- #else
- # include <atomic>
- # define ENTT_MAYBE_ATOMIC(Type) std::atomic<Type>
- #endif
- #ifndef ENTT_ID_TYPE
- # include <cstdint>
- # define ENTT_ID_TYPE std::uint32_t
- #endif
- #ifdef ENTT_SPARSE_PAGE
- static_assert(ENTT_SPARSE_PAGE && ((ENTT_SPARSE_PAGE & (ENTT_SPARSE_PAGE - 1)) == 0), "ENTT_SPARSE_PAGE must be a power of two");
- #else
- # define ENTT_SPARSE_PAGE 4096
- #endif
- #ifdef ENTT_PACKED_PAGE
- static_assert(ENTT_PACKED_PAGE && ((ENTT_PACKED_PAGE & (ENTT_PACKED_PAGE - 1)) == 0), "ENTT_PACKED_PAGE must be a power of two");
- #else
- # 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
- # include <type_traits>
- # define ENTT_IGNORE_IF_EMPTY std::false_type
- #else
- # include <type_traits>
- # define ENTT_IGNORE_IF_EMPTY std::true_type
- #endif
- #ifndef ENTT_STANDARD_CPP
- # 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
- #endif
- // #include "fwd.hpp"
- #ifndef ENTT_CORE_FWD_HPP
- #define ENTT_CORE_FWD_HPP
- #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<>;
- }
- #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<class 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_t = 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_v = 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::disjunction_v<std::is_same<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<class 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;
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- namespace internal {
- template<typename>
- [[nodiscard]] constexpr bool is_equality_comparable(...) { return false; }
- template<typename Type>
- [[nodiscard]] constexpr auto is_equality_comparable(choice_t<0>)
- -> decltype(std::declval<Type>() == std::declval<Type>()) { return true; }
- template<typename Type>
- [[nodiscard]] constexpr auto is_equality_comparable(choice_t<1>)
- -> decltype(std::declval<typename Type::value_type>(), std::declval<Type>() == std::declval<Type>()) {
- if constexpr(std::is_same_v<typename Type::value_type, Type>) {
- return is_equality_comparable<Type>(choice<0>);
- } else {
- return is_equality_comparable<typename Type::value_type>(choice<2>);
- }
- }
- template<typename Type>
- [[nodiscard]] constexpr auto is_equality_comparable(choice_t<2>)
- -> decltype(std::declval<typename Type::mapped_type>(), std::declval<Type>() == std::declval<Type>()) {
- return is_equality_comparable<typename Type::key_type>(choice<2>) && is_equality_comparable<typename Type::mapped_type>(choice<2>);
- }
- }
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /**
- * @brief Provides the member constant `value` to true if a given type is
- * equality comparable, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_equality_comparable: std::bool_constant<internal::is_equality_comparable<Type>(choice<2>)> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<class Type>
- inline constexpr bool is_equality_comparable_v = is_equality_comparable<Type>::value;
- /*! @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 {};
- /*! @copydoc is_iterator */
- template<typename Type>
- struct is_iterator<Type, std::void_t<typename std::iterator_traits<Type>::iterator_category>>
- : std::true_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 of the
- * required iterator type, false otherwise.
- * @tparam Type The type to test.
- * @tparam It Required iterator type.
- */
- template<typename Type, typename It, typename = void>
- struct is_iterator_type: std::false_type {};
- /*! @copydoc is_iterator_type */
- template<typename Type, typename It>
- struct is_iterator_type<Type, It, std::enable_if_t<is_iterator_v<Type> && std::is_same_v<Type, It>>>
- : std::true_type
- {};
- /*! @copydoc is_iterator_type */
- template<typename Type, typename It>
- struct is_iterator_type<Type, It, std::enable_if_t<!std::is_same_v<Type, It>, std::void_t<typename It::iterator_type>>>
- : is_iterator_type<Type, typename It::iterator_type>
- {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- * @tparam It Required iterator type.
- */
- template<typename Type, typename It>
- inline constexpr bool is_iterator_type_v = is_iterator_type<Type, It>::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;
- }
- #endif
- // #include "../config/config.h"
- 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...>{};
- }
- }
- /**
- * 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
- : fn{nullptr}, data{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 {
- data = 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 {
- data = &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 {
- data = 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 {
- fn = function;
- data = payload;
- }
- /**
- * @brief Resets a delegate.
- *
- * After a reset, a delegate cannot be invoked anymore.
- */
- void reset() ENTT_NOEXCEPT {
- fn = nullptr;
- data = 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 * instance() const ENTT_NOEXCEPT {
- return data;
- }
- /**
- * @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(data, 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 test also data
- 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 && data == other.data;
- }
- private:
- function_type *fn;
- const void *data;
- };
- /**
- * @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...)>;
- }
- #endif
- // #include "fwd.hpp"
- #ifndef ENTT_SIGNAL_FWD_HPP
- #define ENTT_SIGNAL_FWD_HPP
- namespace entt {
- template<typename>
- class delegate;
- class dispatcher;
- template<typename>
- class emitter;
- class connection;
- struct scoped_connection;
- template<typename>
- class sink;
- template<typename>
- class sigh;
- }
- #endif
- 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 Function A valid function type.
- */
- template<typename Function>
- 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 Function A valid function type.
- */
- template<typename Function>
- 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.
- */
- template<typename Ret, typename... Args>
- class sigh<Ret(Args...)> {
- /*! @brief A sink is allowed to modify a signal. */
- friend class sink<Ret(Args...)>;
- public:
- /*! @brief Unsigned integer type. */
- using size_type = std::size_t;
- /*! @brief Sink type. */
- using sink_type = sink<Ret(Args...)>;
- /**
- * @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:
- std::vector<delegate<Ret(Args...)>> 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 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 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.
- */
- template<typename Ret, typename... Args>
- class sink<Ret(Args...)> {
- using signal_type = sigh<Ret(Args...)>;
- using difference_type = typename std::iterator_traits<typename decltype(signal_type::calls)::iterator>::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...)> &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 = std::distance(it, calls.cend());
- 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 = std::distance(it, calls.cend());
- 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.instance() == value_or_instance;
- });
- other.offset = std::distance(it, calls.cend());
- }
- 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;
- calls.erase(std::remove_if(calls.begin(), calls.end(), [value_or_instance](const auto &delegate) {
- return delegate.instance() == value_or_instance;
- }), 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 function 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.
- */
- template<typename Ret, typename... Args>
- sink(sigh<Ret(Args...)> &)
- -> sink<Ret(Args...)>;
- }
- #endif
- // #include "component.hpp"
- #ifndef ENTT_ENTITY_COMPONENT_HPP
- #define ENTT_ENTITY_COMPONENT_HPP
- #include <type_traits>
- // #include "../config/config.h"
- namespace entt {
- /*! @brief Commonly used default traits for all types. */
- struct basic_component_traits {
- /*! @brief Pointer stability, default is `std::false_type`. */
- using in_place_delete = std::false_type;
- /*! @brief Empty type optimization, default is `ENTT_IGNORE_IF_EMPTY`. */
- using ignore_if_empty = ENTT_IGNORE_IF_EMPTY;
- };
- /**
- * @brief Common way to access various properties of components.
- * @tparam Type Type of component.
- */
- template<typename Type, typename = void>
- struct component_traits: basic_component_traits {
- static_assert(std::is_same_v<std::decay_t<Type>, Type>, "Unsupported type");
- };
- }
- #endif
- // #include "entity.hpp"
- // #include "fwd.hpp"
- // #include "sparse_set.hpp"
- namespace entt {
- /**
- * @brief Basic storage implementation.
- *
- * This class is a refinement of a sparse set that associates an object to an
- * entity. The main purpose of this class is to extend sparse sets to store
- * components in a registry. It guarantees fast access both to the elements and
- * to the entities.
- *
- * @note
- * Entities and objects have the same order.
- *
- * @note
- * 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.
- *
- * @sa sparse_set<Entity>
- *
- * @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 = void>
- class basic_storage_impl: public basic_sparse_set<Entity, typename std::allocator_traits<Allocator>::template rebind_alloc<Entity>> {
- static constexpr auto packed_page = ENTT_PACKED_PAGE;
- using comp_traits = component_traits<Type>;
- using underlying_type = basic_sparse_set<Entity, typename std::allocator_traits<Allocator>::template rebind_alloc<Entity>>;
- using difference_type = typename entt_traits<Entity>::difference_type;
- using alloc_traits = typename std::allocator_traits<Allocator>::template rebind_traits<Type>;
- using alloc_pointer = typename alloc_traits::pointer;
- using alloc_const_pointer = typename alloc_traits::const_pointer;
- using bucket_alloc_traits = typename std::allocator_traits<Allocator>::template rebind_traits<alloc_pointer>;
- using bucket_alloc_pointer = typename bucket_alloc_traits::pointer;
- using bucket_alloc_const_type = typename std::allocator_traits<Allocator>::template rebind_alloc<alloc_const_pointer>;
- using bucket_alloc_const_pointer = typename std::allocator_traits<bucket_alloc_const_type>::const_pointer;
- static_assert(alloc_traits::propagate_on_container_move_assignment::value);
- static_assert(bucket_alloc_traits::propagate_on_container_move_assignment::value);
- template<typename Value>
- struct storage_iterator final {
- using difference_type = typename basic_storage_impl::difference_type;
- using value_type = Value;
- using pointer = value_type *;
- using reference = value_type &;
- using iterator_category = std::random_access_iterator_tag;
- storage_iterator() ENTT_NOEXCEPT = default;
- storage_iterator(bucket_alloc_pointer const *ref, const typename basic_storage_impl::difference_type idx) ENTT_NOEXCEPT
- : packed{ref},
- index{idx}
- {}
- storage_iterator & operator++() ENTT_NOEXCEPT {
- return --index, *this;
- }
- storage_iterator operator++(int) ENTT_NOEXCEPT {
- storage_iterator orig = *this;
- return ++(*this), orig;
- }
- storage_iterator & operator--() ENTT_NOEXCEPT {
- return ++index, *this;
- }
- storage_iterator operator--(int) ENTT_NOEXCEPT {
- storage_iterator orig = *this;
- return operator--(), orig;
- }
- storage_iterator & operator+=(const difference_type value) ENTT_NOEXCEPT {
- index -= 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);
- }
- difference_type operator-(const storage_iterator &other) const ENTT_NOEXCEPT {
- return other.index - index;
- }
- [[nodiscard]] reference operator[](const difference_type value) const ENTT_NOEXCEPT {
- const auto pos = size_type(index-value-1);
- return (*packed)[page(pos)][offset(pos)];
- }
- [[nodiscard]] bool operator==(const storage_iterator &other) const ENTT_NOEXCEPT {
- return other.index == index;
- }
- [[nodiscard]] bool operator!=(const storage_iterator &other) const ENTT_NOEXCEPT {
- return !(*this == other);
- }
- [[nodiscard]] bool operator<(const storage_iterator &other) const ENTT_NOEXCEPT {
- return index > other.index;
- }
- [[nodiscard]] bool operator>(const storage_iterator &other) const ENTT_NOEXCEPT {
- return index < other.index;
- }
- [[nodiscard]] bool operator<=(const storage_iterator &other) const ENTT_NOEXCEPT {
- return !(*this > other);
- }
- [[nodiscard]] bool operator>=(const storage_iterator &other) const ENTT_NOEXCEPT {
- return !(*this < other);
- }
- [[nodiscard]] pointer operator->() const ENTT_NOEXCEPT {
- const auto pos = size_type(index-1u);
- return std::addressof((*packed)[page(pos)][offset(pos)]);
- }
- [[nodiscard]] reference operator*() const ENTT_NOEXCEPT {
- return *operator->();
- }
- private:
- bucket_alloc_pointer const *packed;
- difference_type index;
- };
- [[nodiscard]] static auto page(const std::size_t pos) ENTT_NOEXCEPT {
- return pos / packed_page;
- }
- [[nodiscard]] static auto offset(const std::size_t pos) ENTT_NOEXCEPT {
- return pos & (packed_page - 1);
- }
- void release_memory() {
- if(packed) {
- // no-throw stable erase iteration
- underlying_type::clear();
- for(size_type pos{}; pos < bucket; ++pos) {
- alloc_traits::deallocate(allocator, packed[pos], packed_page);
- bucket_alloc_traits::destroy(bucket_allocator, std::addressof(packed[pos]));
- }
- bucket_alloc_traits::deallocate(bucket_allocator, packed, bucket);
- }
- }
- void assure_at_least(const std::size_t last) {
- if(const auto idx = page(last - 1u); !(idx < bucket)) {
- const size_type sz = idx + 1u;
- const auto mem = bucket_alloc_traits::allocate(bucket_allocator, sz);
- std::uninitialized_copy(packed, packed + bucket, mem);
- size_type pos{};
- ENTT_TRY {
- for(pos = bucket; pos < sz; ++pos) {
- auto pg = alloc_traits::allocate(allocator, packed_page);
- bucket_alloc_traits::construct(bucket_allocator, std::addressof(mem[pos]), pg);
- }
- } ENTT_CATCH {
- for(auto next = bucket; next < pos; ++next) {
- alloc_traits::deallocate(allocator, mem[next], packed_page);
- }
- std::destroy(mem, mem + pos);
- bucket_alloc_traits::deallocate(bucket_allocator, mem, sz);
- ENTT_THROW;
- }
- std::destroy(packed, packed + bucket);
- bucket_alloc_traits::deallocate(bucket_allocator, packed, bucket);
- packed = mem;
- bucket = sz;
- }
- }
- void release_unused_pages() {
- if(const auto length = underlying_type::size() / packed_page; length < bucket) {
- const auto mem = bucket_alloc_traits::allocate(bucket_allocator, length);
- std::uninitialized_copy(packed, packed + length, mem);
- for(auto pos = length; pos < bucket; ++pos) {
- alloc_traits::deallocate(allocator, packed[pos], packed_page);
- bucket_alloc_traits::destroy(bucket_allocator, std::addressof(packed[pos]));
- }
- bucket_alloc_traits::deallocate(bucket_allocator, packed, bucket);
- packed = mem;
- bucket = length;
- }
- }
- template<typename... Args>
- auto & push_at(const std::size_t pos, Args &&... args) {
- ENTT_ASSERT(pos < (bucket * packed_page), "Out of bounds index");
- auto *instance = std::addressof(packed[page(pos)][offset(pos)]);
- if constexpr(std::is_aggregate_v<value_type>) {
- alloc_traits::construct(allocator, instance, Type{std::forward<Args>(args)...});
- } else {
- alloc_traits::construct(allocator, instance, std::forward<Args>(args)...);
- }
- return *instance;
- }
- void pop_at(const std::size_t pos) {
- alloc_traits::destroy(allocator, std::addressof(packed[page(pos)][offset(pos)]));
- }
- protected:
- /*! @copydoc basic_sparse_set::swap_at */
- void swap_at(const std::size_t lhs, const std::size_t rhs) final {
- std::swap(packed[page(lhs)][offset(lhs)], packed[page(rhs)][offset(rhs)]);
- }
- /*! @copydoc basic_sparse_set::move_and_pop */
- void move_and_pop(const std::size_t from, const std::size_t to) final {
- push_at(to, std::move(packed[page(from)][offset(from)]));
- pop_at(from);
- }
- /*! @copydoc basic_sparse_set::swap_and_pop */
- void swap_and_pop(const Entity entt, void *ud) override {
- const auto pos = underlying_type::index(entt);
- const auto last = underlying_type::size() - 1u;
- auto &&elem = packed[page(pos)][offset(pos)];
- // support for nosy destructors
- [[maybe_unused]] auto unused = std::move(elem);
- elem = std::move(packed[page(last)][offset(last)]);
- pop_at(last);
- underlying_type::swap_and_pop(entt, ud);
- }
- /*! @copydoc basic_sparse_set::in_place_pop */
- void in_place_pop(const Entity entt, void *ud) override {
- const auto pos = underlying_type::index(entt);
- underlying_type::in_place_pop(entt, ud);
- // support for nosy destructors
- pop_at(pos);
- }
- public:
- /*! @brief Allocator type. */
- using allocator_type = typename alloc_traits::allocator_type;
- /*! @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 = bucket_alloc_pointer;
- /*! @brief Constant pointer type to contained elements. */
- using const_pointer = bucket_alloc_const_pointer;
- /*! @brief Random access iterator type. */
- using iterator = storage_iterator<value_type>;
- /*! @brief Constant random access iterator type. */
- using const_iterator = storage_iterator<const value_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 Default constructor.
- * @param alloc Allocator to use (possibly default-constructed).
- */
- explicit basic_storage_impl(const allocator_type &alloc = {})
- : underlying_type{deletion_policy{comp_traits::in_place_delete::value}, alloc},
- allocator{alloc},
- bucket_allocator{alloc},
- packed{bucket_alloc_traits::allocate(bucket_allocator, 0u)},
- bucket{}
- {}
- /**
- * @brief Move constructor.
- * @param other The instance to move from.
- */
- basic_storage_impl(basic_storage_impl &&other) ENTT_NOEXCEPT
- : underlying_type{std::move(other)},
- allocator{std::move(other.allocator)},
- bucket_allocator{std::move(other.bucket_allocator)},
- packed{std::exchange(other.packed, bucket_alloc_pointer{})},
- bucket{std::exchange(other.bucket, 0u)}
- {}
- /*! @brief Default destructor. */
- ~basic_storage_impl() override {
- release_memory();
- }
- /**
- * @brief Move assignment operator.
- * @param other The instance to move from.
- * @return This sparse set.
- */
- basic_storage_impl & operator=(basic_storage_impl &&other) ENTT_NOEXCEPT {
- release_memory();
- underlying_type::operator=(std::move(other));
- allocator = std::move(other.allocator);
- bucket_allocator = std::move(other.bucket_allocator);
- packed = std::exchange(other.packed, bucket_alloc_pointer{});
- bucket = std::exchange(other.bucket, 0u);
- return *this;
- }
- /**
- * @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) {
- underlying_type::reserve(cap);
- if(cap > underlying_type::size()) {
- assure_at_least(cap);
- }
- }
- /**
- * @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 {
- return bucket * packed_page;
- }
- /*! @brief Requests the removal of unused capacity. */
- void shrink_to_fit() {
- underlying_type::shrink_to_fit();
- release_unused_pages();
- }
- /**
- * @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;
- }
- /*! @copydoc raw */
- [[nodiscard]] pointer raw() ENTT_NOEXCEPT {
- return packed;
- }
- /**
- * @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 difference_type pos = underlying_type::size();
- return const_iterator{std::addressof(packed), pos};
- }
- /*! @copydoc cbegin */
- [[nodiscard]] const_iterator begin() const ENTT_NOEXCEPT {
- return cbegin();
- }
- /*! @copydoc begin */
- [[nodiscard]] iterator begin() ENTT_NOEXCEPT {
- const difference_type pos = underlying_type::size();
- return iterator{std::addressof(packed), 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{std::addressof(packed), {}};
- }
- /*! @copydoc cend */
- [[nodiscard]] const_iterator end() const ENTT_NOEXCEPT {
- return cend();
- }
- /*! @copydoc end */
- [[nodiscard]] iterator end() ENTT_NOEXCEPT {
- return iterator{std::addressof(packed), {}};
- }
- /**
- * @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 entity identifier.
- * @return The object assigned to the entity.
- */
- [[nodiscard]] const value_type & get(const entity_type entt) const ENTT_NOEXCEPT {
- const auto idx = underlying_type::index(entt);
- return packed[page(idx)][offset(idx)];
- }
- /*! @copydoc get */
- [[nodiscard]] value_type & get(const entity_type entt) ENTT_NOEXCEPT {
- return const_cast<value_type &>(std::as_const(*this).get(entt));
- }
- /**
- * @brief Assigns an entity to a storage and constructs its object.
- *
- * This version accept both types that can be constructed in place directly
- * and types like aggregates that do not work well with a placement new as
- * performed usually under the hood during an _emplace back_.
- *
- * @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 entity 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) {
- const auto pos = underlying_type::slot();
- assure_at_least(pos + 1u);
- auto &value = push_at(pos, std::forward<Args>(args)...);
- ENTT_TRY {
- [[maybe_unused]] const auto curr = underlying_type::emplace(entt);
- ENTT_ASSERT(pos == curr, "Misplaced component");
- } ENTT_CATCH {
- pop_at(pos);
- ENTT_THROW;
- }
- return value;
- }
- /**
- * @brief Updates the instance assigned to a given entity in-place.
- * @tparam Func Types of the function objects to invoke.
- * @param entt A valid entity identifier.
- * @param func Valid function objects.
- * @return A reference to the updated instance.
- */
- template<typename... Func>
- decltype(auto) patch(const entity_type entt, Func &&... func) {
- const auto idx = underlying_type::index(entt);
- auto &&elem = packed[page(idx)][offset(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 = {}) {
- const auto cap = underlying_type::size() + std::distance(first, last);
- underlying_type::reserve(cap);
- assure_at_least(cap);
- for(; first != last; ++first) {
- push_at(underlying_type::size(), value);
- ENTT_TRY {
- underlying_type::emplace_back(*first);
- } ENTT_CATCH {
- pop_at(underlying_type::size());
- ENTT_THROW;
- }
- }
- }
- /**
- * @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<std::decay_t<typename std::iterator_traits<CIt>::value_type>, value_type>>>
- void insert(EIt first, EIt last, CIt from) {
- const auto cap = underlying_type::size() + std::distance(first, last);
- underlying_type::reserve(cap);
- assure_at_least(cap);
- for(; first != last; ++first, ++from) {
- push_at(underlying_type::size(), *from);
- ENTT_TRY {
- underlying_type::emplace_back(*first);
- } ENTT_CATCH {
- pop_at(underlying_type::size());
- ENTT_THROW;
- }
- }
- }
- /**
- * @brief Sort 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 one of the following:
- *
- * @code{.cpp}
- * bool(const Entity, const Entity);
- * bool(const Type &, const Type &);
- * @endcode
- *
- * Moreover, the comparison function object shall induce a
- * _strict weak ordering_ on the values.
- *
- * The sort function oject 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.
- *
- * @warning
- * Empty types are never instantiated. Therefore, only comparison function
- * objects that require to return entities rather than components are
- * accepted.
- *
- * @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) {
- if constexpr(std::is_invocable_v<Compare, const value_type &, const value_type &>) {
- underlying_type::sort_n(length, [this, compare = std::move(compare)](const auto lhs, const auto rhs) {
- const auto ilhs = underlying_type::index(lhs), irhs = underlying_type::index(rhs);
- return compare(std::as_const(packed[page(ilhs)][offset(ilhs)]), std::as_const(packed[page(irhs)][offset(irhs)]));
- }, std::move(algo), std::forward<Args>(args)...);
- } else {
- underlying_type::sort_n(length, std::move(compare), std::move(algo), std::forward<Args>(args)...);
- }
- }
- /**
- * @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) {
- sort_n(underlying_type::size(), std::move(compare), std::move(algo), std::forward<Args>(args)...);
- }
- private:
- typename alloc_traits::allocator_type allocator;
- typename bucket_alloc_traits::allocator_type bucket_allocator;
- bucket_alloc_pointer packed;
- size_type bucket;
- };
- /*! @copydoc basic_storage_impl */
- template<typename Entity, typename Type, typename Allocator>
- class basic_storage_impl<Entity, Type, Allocator, std::enable_if_t<component_traits<Type>::ignore_if_empty::value && std::is_empty_v<Type>>>
- : public basic_sparse_set<Entity, typename std::allocator_traits<Allocator>::template rebind_alloc<Entity>>
- {
- using comp_traits = component_traits<Type>;
- using underlying_type = basic_sparse_set<Entity, typename std::allocator_traits<Allocator>::template rebind_alloc<Entity>>;
- using alloc_traits = typename std::allocator_traits<Allocator>::template rebind_traits<Type>;
- public:
- /*! @brief Allocator type. */
- using allocator_type = typename alloc_traits::allocator_type;
- /*! @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 Default constructor.
- * @param alloc Allocator to use (possibly default-constructed).
- */
- explicit basic_storage_impl(const allocator_type &alloc = {})
- : underlying_type{deletion_policy{comp_traits::in_place_delete::value}, alloc}
- {}
- /**
- * @brief Fake get function.
- *
- * @warning
- * Attempting to use an entity that doesn't belong to the storage results in
- * undefined behavior.
- *
- * @param entt A valid entity identifier.
- */
- void get([[maybe_unused]] const entity_type entt) const ENTT_NOEXCEPT {
- ENTT_ASSERT(underlying_type::contains(entt), "Storage does not contain entity");
- }
- /**
- * @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 entity identifier.
- * @param args Parameters to use to construct an object for the entity.
- */
- template<typename... Args>
- void emplace(const entity_type entt, Args &&... args) {
- [[maybe_unused]] value_type instance{std::forward<Args>(args)...};
- underlying_type::emplace(entt);
- }
- /**
- * @brief Updates the instance assigned to a given entity in-place.
- * @tparam Func Types of the function objects to invoke.
- * @param entt A valid entity identifier.
- * @param func Valid function objects.
- */
- template<typename... Func>
- void patch([[maybe_unused]] const entity_type entt, Func &&... func) {
- ENTT_ASSERT(underlying_type::contains(entt), "Storage does not contain entity");
- (std::forward<Func>(func)(), ...);
- }
- /**
- * @brief Assigns one or more entities to a storage.
- *
- * @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.
- */
- template<typename It>
- void insert(It first, It last, const value_type & = {}) {
- underlying_type::insert(first, last);
- }
- };
- /**
- * @brief Mixin type to use to wrap basic storage classes.
- * @tparam Type The type of the underlying storage.
- */
- template<typename Type>
- struct storage_adapter_mixin: Type {
- static_assert(std::is_same_v<typename Type::value_type, std::decay_t<typename Type::value_type>>, "Invalid object type");
- /*! @brief Type of the objects assigned to entities. */
- using value_type = typename Type::value_type;
- /*! @brief Underlying entity identifier. */
- using entity_type = typename Type::entity_type;
- /*! @brief Inherited constructors. */
- using Type::Type;
- /**
- * @brief Assigns entities to a storage.
- * @tparam Args Types of arguments to use to construct the object.
- * @param entt A valid entity identifier.
- * @param args Parameters to use to initialize the object.
- * @return A reference to the newly created object.
- */
- template<typename... Args>
- decltype(auto) emplace(basic_registry<entity_type> &, const entity_type entt, Args &&... args) {
- return Type::emplace(entt, std::forward<Args>(args)...);
- }
- /**
- * @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(basic_registry<entity_type> &, It first, It last, Args &&... args) {
- Type::insert(first, last, std::forward<Args>(args)...);
- }
- /**
- * @brief Patches the given instance for an entity.
- * @tparam Func Types of the function objects to invoke.
- * @param entt A valid entity identifier.
- * @param func Valid function objects.
- * @return A reference to the patched instance.
- */
- template<typename... Func>
- decltype(auto) patch(basic_registry<entity_type> &, const entity_type entt, Func &&... func) {
- return Type::patch(entt, std::forward<Func>(func)...);
- }
- };
- /**
- * @brief Mixin type to use to add signal support to storage types.
- * @tparam Type The type of the underlying storage.
- */
- template<typename Type>
- class sigh_storage_mixin final: public Type {
- /*! @copydoc basic_sparse_set::swap_and_pop */
- void swap_and_pop(const typename Type::entity_type entt, void *ud) final {
- ENTT_ASSERT(ud != nullptr, "Invalid pointer to registry");
- destruction.publish(*static_cast<basic_registry<typename Type::entity_type> *>(ud), entt);
- Type::swap_and_pop(entt, ud);
- }
- /*! @copydoc basic_sparse_set::in_place_pop */
- void in_place_pop(const typename Type::entity_type entt, void *ud) final {
- ENTT_ASSERT(ud != nullptr, "Invalid pointer to registry");
- destruction.publish(*static_cast<basic_registry<typename Type::entity_type> *>(ud), entt);
- Type::in_place_pop(entt, ud);
- }
- public:
- /*! @brief Underlying value type. */
- using value_type = typename Type::value_type;
- /*! @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/>
- * The function type for a listener is equivalent to:
- *
- * @code{.cpp}
- * void(basic_registry<entity_type> &, entity_type);
- * @endcode
- *
- * 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/>
- * The function type for a listener is equivalent to:
- *
- * @code{.cpp}
- * void(basic_registry<entity_type> &, entity_type);
- * @endcode
- *
- * 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/>
- * The function type for a listener is equivalent to:
- *
- * @code{.cpp}
- * void(basic_registry<entity_type> &, entity_type);
- * @endcode
- *
- * 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 owner The registry that issued the request.
- * @param entt A valid entity identifier.
- * @param args Parameters to use to initialize the object.
- * @return A reference to the newly created object.
- */
- template<typename... Args>
- decltype(auto) emplace(basic_registry<entity_type> &owner, const entity_type entt, Args &&... args) {
- Type::emplace(entt, std::forward<Args>(args)...);
- construction.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 owner The registry that issued the request.
- * @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(basic_registry<entity_type> &owner, It first, It last, Args &&... args) {
- Type::insert(first, last, std::forward<Args>(args)...);
- if(!construction.empty()) {
- for(; first != last; ++first) {
- construction.publish(owner, *first);
- }
- }
- }
- /**
- * @brief Patches the given instance for an entity.
- * @tparam Func Types of the function objects to invoke.
- * @param owner The registry that issued the request.
- * @param entt A valid entity identifier.
- * @param func Valid function objects.
- * @return A reference to the patched instance.
- */
- template<typename... Func>
- decltype(auto) patch(basic_registry<entity_type> &owner, const entity_type entt, Func &&... func) {
- Type::patch(entt, std::forward<Func>(func)...);
- update.publish(owner, entt);
- return this->get(entt);
- }
- 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{};
- };
- /**
- * @brief Storage implementation dispatcher.
- * @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>
- struct basic_storage: basic_storage_impl<Entity, Type, Allocator> {
- using basic_storage_impl<Entity, Type, Allocator>::basic_storage_impl;
- };
- /**
- * @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>>;
- };
- /**
- * @brief Gets the element assigned to an entity from a storage, if any.
- * @tparam Type Storage type.
- * @param container A valid instance of a storage class.
- * @param entt A valid entity identifier.
- * @return A possibly empty tuple containing the requested element.
- */
- template<typename Type>
- [[nodiscard]] auto get_as_tuple([[maybe_unused]] Type &container, [[maybe_unused]] const typename Type::entity_type entt) {
- static_assert(std::is_same_v<std::remove_const_t<Type>, typename storage_traits<typename Type::entity_type, typename Type::value_type>::storage_type>, "Invalid storage");
- if constexpr(std::is_void_v<decltype(container.get({}))>) {
- return std::make_tuple();
- } else {
- return std::forward_as_tuple(container.get(entt));
- }
- }
- }
- #endif
- // #include "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{};
- }
- #endif
- 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...>
- 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 Exclude Types of components used to filter the group.
- * @tparam Get Type of components observed by the group.
- */
- template<typename Entity, typename... Exclude, typename... Get>
- class basic_group<Entity, exclude_t<Exclude...>, get_t<Get...>> final {
- /*! @brief A registry is allowed to create groups. */
- friend class basic_registry<Entity>;
- using basic_common_type = basic_sparse_set<Entity>;
- template<typename Component>
- using storage_type = constness_as_t<typename storage_traits<Entity, std::remove_const_t<Component>>::storage_type, Component>;
- class iterable final {
- template<typename It>
- struct iterable_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 = void;
- using reference = value_type;
- using iterator_category = std::input_iterator_tag;
- template<typename... Args>
- iterable_iterator(It from, const std::tuple<storage_type<Get> *...> &args) ENTT_NOEXCEPT
- : it{from},
- pools{args}
- {}
- iterable_iterator & operator++() ENTT_NOEXCEPT {
- return ++it, *this;
- }
- iterable_iterator operator++(int) ENTT_NOEXCEPT {
- iterable_iterator orig = *this;
- return ++(*this), orig;
- }
- [[nodiscard]] reference operator*() const ENTT_NOEXCEPT {
- const auto entt = *it;
- return std::tuple_cat(std::make_tuple(entt), get_as_tuple(*std::get<storage_type<Get> *>(pools), entt)...);
- }
- [[nodiscard]] bool operator==(const iterable_iterator &other) const ENTT_NOEXCEPT {
- return other.it == it;
- }
- [[nodiscard]] bool operator!=(const iterable_iterator &other) const ENTT_NOEXCEPT {
- return !(*this == other);
- }
- private:
- It it;
- std::tuple<storage_type<Get> *...> pools;
- };
- public:
- using iterator = iterable_iterator<typename basic_common_type::iterator>;
- using reverse_iterator = iterable_iterator<typename basic_common_type::reverse_iterator>;
- iterable(basic_common_type * const ref, const std::tuple<storage_type<Get> *...> &cpools)
- : handler{ref},
- pools{cpools}
- {}
- [[nodiscard]] iterator begin() const ENTT_NOEXCEPT {
- return handler ? iterator{handler->begin(), pools} : iterator{{}, pools};
- }
- [[nodiscard]] iterator end() const ENTT_NOEXCEPT {
- return handler ? iterator{handler->end(), pools} : iterator{{}, pools};
- }
- [[nodiscard]] reverse_iterator rbegin() const ENTT_NOEXCEPT {
- return handler ? reverse_iterator{handler->rbegin(), pools} : reverse_iterator{{}, pools};
- }
- [[nodiscard]] reverse_iterator rend() const ENTT_NOEXCEPT {
- return handler ? reverse_iterator{handler->rend(), pools} : reverse_iterator{{}, pools};
- }
- private:
- basic_common_type * const handler;
- const 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 Random access iterator type. */
- using iterator = typename basic_common_type::iterator;
- /*! @brief Reversed iterator type. */
- using reverse_iterator = typename basic_common_type::reverse_iterator;
- /*! @brief Iterable group type. */
- using iterable_group = iterable;
- /*! @brief Default constructor to use to create empty, invalid groups. */
- basic_group() ENTT_NOEXCEPT
- : handler{}
- {}
- /**
- * @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 Direct access to the list of entities.
- *
- * The returned pointer is such that range `[data(), data() + size())` is
- * always a valid range, even if the container is empty.
- *
- * @return A pointer to the array of entities.
- */
- [[nodiscard]] auto data() const ENTT_NOEXCEPT {
- return *this ? handler->data() : nullptr;
- }
- /**
- * @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 {
- 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 {
- const auto it = rbegin();
- return it != rend() ? *it : null;
- }
- /**
- * @brief Finds an entity.
- * @param entt A valid entity 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 {
- 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 entity identifier.
- * @return True if the group contains the given entity, false otherwise.
- */
- [[nodiscard]] bool contains(const entity_type entt) const {
- 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 Component Types of components to get.
- * @param entt A valid entity identifier.
- * @return The components assigned to the entity.
- */
- template<typename... Component>
- [[nodiscard]] decltype(auto) get(const entity_type entt) const {
- ENTT_ASSERT(contains(entt), "Group does not contain entity");
- if constexpr(sizeof...(Component) == 0) {
- return std::tuple_cat(get_as_tuple(*std::get<storage_type<Get> *>(pools), entt)...);
- } else if constexpr(sizeof...(Component) == 1) {
- return (std::get<storage_type<Component> *>(pools)->get(entt), ...);
- } else {
- return std::tuple_cat(get_as_tuple(*std::get<storage_type<Component> *>(pools), 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_ the 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_group each() const ENTT_NOEXCEPT {
- return iterable_group{handler, 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 oject 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 Component 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... Component, typename Compare, typename Sort = std_sort, typename... Args>
- void sort(Compare compare, Sort algo = Sort{}, Args &&... args) {
- if(*this) {
- if constexpr(sizeof...(Component) == 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 if constexpr(sizeof...(Component) == 1) {
- handler->sort([this, compare = std::move(compare)](const entity_type lhs, const entity_type rhs) {
- return compare((std::get<storage_type<Component> *>(pools)->get(lhs), ...), (std::get<storage_type<Component> *>(pools)->get(rhs), ...));
- }, std::move(algo), std::forward<Args>(args)...);
- } else {
- handler->sort([this, compare = std::move(compare)](const entity_type lhs, const entity_type rhs) {
- return compare(std::forward_as_tuple(std::get<storage_type<Component> *>(pools)->get(lhs)...), std::forward_as_tuple(std::get<storage_type<Component> *>(pools)->get(rhs)...));
- }, 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 Component Type of component to use to impose the order.
- */
- template<typename Component>
- void sort() const {
- if(*this) {
- handler->respect(*std::get<storage_type<Component> *>(pools));
- }
- }
- private:
- basic_common_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 Exclude Types of components used to filter the group.
- * @tparam Get Types of components observed by the group.
- * @tparam Owned Types of components owned by the group.
- */
- template<typename Entity, typename... Exclude, typename... Get, typename... Owned>
- class basic_group<Entity, exclude_t<Exclude...>, get_t<Get...>, Owned...> final {
- /*! @brief A registry is allowed to create groups. */
- friend class basic_registry<Entity>;
- using basic_common_type = basic_sparse_set<Entity>;
- template<typename Component>
- using storage_type = constness_as_t<typename storage_traits<Entity, std::remove_const_t<Component>>::storage_type, Component>;
- class iterable final {
- template<typename, typename>
- struct iterable_iterator;
- template<typename It, typename... OIt>
- struct iterable_iterator<It, type_list<OIt...>> final {
- using difference_type = std::ptrdiff_t;
- using value_type = decltype(std::tuple_cat(std::tuple<Entity>{}, std::declval<basic_group>().get({})));
- using pointer = void;
- using reference = value_type;
- using iterator_category = std::input_iterator_tag;
- template<typename... Other>
- iterable_iterator(It from, const std::tuple<Other...> &other, const std::tuple<storage_type<Get> *...> &cpools) ENTT_NOEXCEPT
- : it{from},
- owned{std::get<OIt>(other)...},
- get{cpools}
- {}
- iterable_iterator & operator++() ENTT_NOEXCEPT {
- return ++it, (++std::get<OIt>(owned), ...), *this;
- }
- iterable_iterator operator++(int) ENTT_NOEXCEPT {
- iterable_iterator orig = *this;
- return ++(*this), orig;
- }
- [[nodiscard]] reference operator*() const ENTT_NOEXCEPT {
- return std::tuple_cat(
- std::make_tuple(*it),
- std::forward_as_tuple(*std::get<OIt>(owned)...),
- get_as_tuple(*std::get<storage_type<Get> *>(get), *it)...
- );
- }
- [[nodiscard]] bool operator==(const iterable_iterator &other) const ENTT_NOEXCEPT {
- return other.it == it;
- }
- [[nodiscard]] bool operator!=(const iterable_iterator &other) const ENTT_NOEXCEPT {
- return !(*this == other);
- }
- private:
- It it;
- std::tuple<OIt...> owned;
- std::tuple<storage_type<Get> *...> get;
- };
- public:
- using iterator = iterable_iterator<
- typename basic_common_type::iterator,
- type_list_cat_t<std::conditional_t<std::is_void_v<decltype(std::declval<storage_type<Owned>>().get({}))>, type_list<>, type_list<decltype(std::declval<storage_type<Owned>>().end())>>...>
- >;
- using reverse_iterator = iterable_iterator<
- typename basic_common_type::reverse_iterator,
- type_list_cat_t<std::conditional_t<std::is_void_v<decltype(std::declval<storage_type<Owned>>().get({}))>, type_list<>, type_list<decltype(std::declval<storage_type<Owned>>().rbegin())>>...>
- >;
- iterable(std::tuple<storage_type<Owned> *..., storage_type<Get> *...> cpools, const std::size_t * const extent)
- : pools{cpools},
- length{extent}
- {}
- [[nodiscard]] iterator begin() const ENTT_NOEXCEPT {
- return length ? iterator{
- std::get<0>(pools)->basic_common_type::end() - *length,
- std::make_tuple((std::get<storage_type<Owned> *>(pools)->end() - *length)...),
- std::make_tuple(std::get<storage_type<Get> *>(pools)...)
- } : iterator{{}, std::make_tuple(decltype(std::get<storage_type<Owned> *>(pools)->end()){}...), std::make_tuple(std::get<storage_type<Get> *>(pools)...)};
- }
- [[nodiscard]] iterator end() const ENTT_NOEXCEPT {
- return length ? iterator{
- std::get<0>(pools)->basic_common_type::end(),
- std::make_tuple((std::get<storage_type<Owned> *>(pools)->end())...),
- std::make_tuple(std::get<storage_type<Get> *>(pools)...)
- } : iterator{{}, std::make_tuple(decltype(std::get<storage_type<Owned> *>(pools)->end()){}...), std::make_tuple(std::get<storage_type<Get> *>(pools)...)};
- }
- [[nodiscard]] reverse_iterator rbegin() const ENTT_NOEXCEPT {
- return length ? reverse_iterator{
- std::get<0>(pools)->basic_common_type::rbegin(),
- std::make_tuple((std::get<storage_type<Owned> *>(pools)->rbegin())...),
- std::make_tuple(std::get<storage_type<Get> *>(pools)...)
- } : reverse_iterator{{}, std::make_tuple(decltype(std::get<storage_type<Owned> *>(pools)->rbegin()){}...), std::make_tuple(std::get<storage_type<Get> *>(pools)...)};
- }
- [[nodiscard]] reverse_iterator rend() const ENTT_NOEXCEPT {
- return length ? reverse_iterator{
- std::get<0>(pools)->basic_common_type::rbegin() + *length,
- std::make_tuple((std::get<storage_type<Owned> *>(pools)->rbegin() + *length)...),
- std::make_tuple(std::get<storage_type<Get> *>(pools)...)
- } : reverse_iterator{{}, std::make_tuple(decltype(std::get<storage_type<Owned> *>(pools)->rbegin()){}...), std::make_tuple(std::get<storage_type<Get> *>(pools)...)};
- }
- private:
- const std::tuple<storage_type<Owned> *..., storage_type<Get> *...> pools;
- const std::size_t * const length;
- };
- 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 Random access iterator type. */
- using iterator = typename basic_common_type::iterator;
- /*! @brief Reversed iterator type. */
- using reverse_iterator = typename basic_common_type::reverse_iterator;
- /*! @brief Iterable group type. */
- using iterable_group = iterable;
- /*! @brief Default constructor to use to create empty, invalid groups. */
- basic_group() ENTT_NOEXCEPT
- : length{}
- {}
- /**
- * @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 Direct access to the raw representation offered by the storage.
- *
- * @warning
- * This function is only available for owned types.
- *
- * @tparam Component Type of component in which one is interested.
- * @return A pointer to the array of components.
- */
- template<typename Component>
- [[nodiscard]] auto raw() const ENTT_NOEXCEPT {
- static_assert((std::is_same_v<Component, Owned> || ...), "Non-owned type");
- auto *cpool = std::get<storage_type<Component> *>(pools);
- return cpool ? cpool->raw() : decltype(cpool->raw()){};
- }
- /**
- * @brief Direct access to the list of entities.
- *
- * The returned pointer is such that range `[data(), data() + size())` is
- * always a valid range, even if the container is empty.
- *
- * @return A pointer to the array of entities.
- */
- [[nodiscard]] auto data() const ENTT_NOEXCEPT {
- return *this ? std::get<0>(pools)->data() : nullptr;
- }
- /**
- * @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)->basic_common_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)->basic_common_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)->basic_common_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)->basic_common_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 {
- 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 {
- const auto it = rbegin();
- return it != rend() ? *it : null;
- }
- /**
- * @brief Finds an entity.
- * @param entt A valid entity 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 {
- 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 entity identifier.
- * @return True if the group contains the given entity, false otherwise.
- */
- [[nodiscard]] bool contains(const entity_type entt) const {
- 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 Component Types of components to get.
- * @param entt A valid entity identifier.
- * @return The components assigned to the entity.
- */
- template<typename... Component>
- [[nodiscard]] decltype(auto) get(const entity_type entt) const {
- ENTT_ASSERT(contains(entt), "Group does not contain entity");
- if constexpr(sizeof...(Component) == 0) {
- return std::tuple_cat(get_as_tuple(*std::get<storage_type<Owned> *>(pools), entt)..., get_as_tuple(*std::get<storage_type<Get> *>(pools), entt)...);
- } else if constexpr(sizeof...(Component) == 1) {
- return (std::get<storage_type<Component> *>(pools)->get(entt), ...);
- } else {
- return std::tuple_cat(get_as_tuple(*std::get<storage_type<Component> *>(pools), 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_ the 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_group each() const ENTT_NOEXCEPT {
- return iterable_group{pools, length};
- }
- /**
- * @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 oject 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 Component 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... Component, 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...(Component) == 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 if constexpr(sizeof...(Component) == 1) {
- cpool->sort_n(*length, [this, compare = std::move(compare)](const entity_type lhs, const entity_type rhs) {
- return compare((std::get<storage_type<Component> *>(pools)->get(lhs), ...), (std::get<storage_type<Component> *>(pools)->get(rhs), ...));
- }, std::move(algo), std::forward<Args>(args)...);
- } else {
- cpool->sort_n(*length, [this, compare = std::move(compare)](const entity_type lhs, const entity_type rhs) {
- return compare(std::forward_as_tuple(std::get<storage_type<Component> *>(pools)->get(lhs)...), std::forward_as_tuple(std::get<storage_type<Component> *>(pools)->get(rhs)...));
- }, 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(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;
- };
- }
- #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 "../core/algorithm.hpp"
- // #include "../core/any.hpp"
- #ifndef ENTT_CORE_ANY_HPP
- #define ENTT_CORE_ANY_HPP
- #include <cstddef>
- #include <functional>
- #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
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_NOEXCEPT noexcept
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_NOEXCEPT
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606L
- # include <new>
- # define ENTT_LAUNDER(expr) std::launder(expr)
- #else
- # define ENTT_LAUNDER(expr) expr
- #endif
- #ifndef ENTT_USE_ATOMIC
- # define ENTT_MAYBE_ATOMIC(Type) Type
- #else
- # include <atomic>
- # define ENTT_MAYBE_ATOMIC(Type) std::atomic<Type>
- #endif
- #ifndef ENTT_ID_TYPE
- # include <cstdint>
- # define ENTT_ID_TYPE std::uint32_t
- #endif
- #ifdef ENTT_SPARSE_PAGE
- static_assert(ENTT_SPARSE_PAGE && ((ENTT_SPARSE_PAGE & (ENTT_SPARSE_PAGE - 1)) == 0), "ENTT_SPARSE_PAGE must be a power of two");
- #else
- # define ENTT_SPARSE_PAGE 4096
- #endif
- #ifdef ENTT_PACKED_PAGE
- static_assert(ENTT_PACKED_PAGE && ((ENTT_PACKED_PAGE & (ENTT_PACKED_PAGE - 1)) == 0), "ENTT_PACKED_PAGE must be a power of two");
- #else
- # 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
- # include <type_traits>
- # define ENTT_IGNORE_IF_EMPTY std::false_type
- #else
- # include <type_traits>
- # define ENTT_IGNORE_IF_EMPTY std::true_type
- #endif
- #ifndef ENTT_STANDARD_CPP
- # 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
- #endif
- namespace entt {
- /*! @brief Identity function object (waiting for C++20). */
- struct identity {
- /**
- * @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;
- };
- }
- #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 "../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 "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;
- };
- }
- /**
- * 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 identifers 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.
- *
- * @tparam Char Character type.
- */
- template<typename Char>
- class basic_hashed_string {
- using traits_type = internal::fnv1a_traits<id_type>;
- struct const_wrapper {
- // non-explicit constructor on purpose
- constexpr const_wrapper(const Char *curr) ENTT_NOEXCEPT: str{curr} {}
- const Char *str;
- };
- // Fowler–Noll–Vo hash function v. 1a - the good
- [[nodiscard]] static constexpr id_type helper(const Char *curr) ENTT_NOEXCEPT {
- auto value = traits_type::offset;
- while(*curr != 0) {
- value = (value ^ static_cast<traits_type::type>(*(curr++))) * traits_type::prime;
- }
- return value;
- }
- public:
- /*! @brief Character type. */
- using value_type = Char;
- /*! @brief Unsigned integer type. */
- using hash_type = id_type;
- /**
- * @brief Returns directly the numeric representation of a string view.
- * @param str Human-readable identifer.
- * @param size Length of the string to hash.
- * @return The numeric representation of the string.
- */
- [[nodiscard]] static constexpr hash_type value(const value_type *str, std::size_t size) ENTT_NOEXCEPT {
- id_type partial{traits_type::offset};
- while(size--) { partial = (partial^(str++)[0])*traits_type::prime; }
- return partial;
- }
- /**
- * @brief Returns directly the numeric representation of a string.
- *
- * Forcing template resolution avoids implicit conversions. An
- * human-readable identifier can be anything but a plain, old bunch of
- * characters.<br/>
- * Example of use:
- * @code{.cpp}
- * const auto value = basic_hashed_string<char>::to_value("my.png");
- * @endcode
- *
- * @tparam N Number of characters of the identifier.
- * @param str Human-readable identifer.
- * @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 helper(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 hash_type value(const_wrapper wrapper) ENTT_NOEXCEPT {
- return helper(wrapper.str);
- }
- /*! @brief Constructs an empty hashed string. */
- constexpr basic_hashed_string() ENTT_NOEXCEPT
- : str{nullptr}, hash{}
- {}
- /**
- * @brief Constructs a hashed string from an array of const characters.
- *
- * Forcing template resolution avoids implicit conversions. An
- * human-readable identifier can be anything but a plain, old bunch of
- * characters.<br/>
- * Example of use:
- * @code{.cpp}
- * basic_hashed_string<char> hs{"my.png"};
- * @endcode
- *
- * @tparam N Number of characters of the identifier.
- * @param curr Human-readable identifer.
- */
- template<std::size_t N>
- constexpr basic_hashed_string(const value_type (&curr)[N]) ENTT_NOEXCEPT
- : str{curr}, hash{helper(curr)}
- {}
- /**
- * @brief Explicit constructor on purpose to avoid constructing a hashed
- * string directly from a `const value_type *`.
- * @param wrapper Helps achieving the purpose by relying on overloading.
- */
- explicit constexpr basic_hashed_string(const_wrapper wrapper) ENTT_NOEXCEPT
- : str{wrapper.str}, hash{helper(wrapper.str)}
- {}
- /**
- * @brief Returns the human-readable representation of a hashed string.
- * @return The string used to initialize the instance.
- */
- [[nodiscard]] constexpr const value_type * data() const ENTT_NOEXCEPT {
- return str;
- }
- /**
- * @brief Returns the numeric representation of a hashed string.
- * @return The numeric representation of the instance.
- */
- [[nodiscard]] constexpr hash_type value() const ENTT_NOEXCEPT {
- return 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 instance.
- */
- [[nodiscard]] constexpr operator hash_type() const ENTT_NOEXCEPT { return value(); }
- /**
- * @brief Compares two hashed strings.
- * @param other Hashed string with which to compare.
- * @return True if the two hashed strings are identical, false otherwise.
- */
- [[nodiscard]] constexpr bool operator==(const basic_hashed_string &other) const ENTT_NOEXCEPT {
- return hash == other.hash;
- }
- private:
- const value_type *str;
- hash_type hash;
- };
- /**
- * @brief Deduction guide.
- *
- * It allows to deduce the character type of the hashed string directly from a
- * human-readable identifer provided to the constructor.
- *
- * @tparam Char Character type.
- * @tparam N Number of characters of the identifier.
- * @param str Human-readable identifer.
- */
- 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 == 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 entt::hashed_string operator"" _hs(const char *str, std::size_t) ENTT_NOEXCEPT {
- return entt::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 entt::hashed_wstring operator"" _hws(const wchar_t *str, std::size_t) ENTT_NOEXCEPT {
- return entt::hashed_wstring{str};
- }
- }
- }
- #endif
- // #include "fwd.hpp"
- namespace entt {
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- namespace internal {
- struct ENTT_API type_seq 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;
- }
- }
- /**
- * 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_seq 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_seq::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_seq<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. */
- class type_info final {
- template<typename>
- friend type_info type_id() ENTT_NOEXCEPT;
- type_info(id_type seq_v, id_type hash_v, std::string_view name_v) ENTT_NOEXCEPT
- : seq_value{seq_v},
- hash_value{hash_v},
- name_value{name_v}
- {}
- public:
- /*! @brief Default constructor. */
- type_info() ENTT_NOEXCEPT
- : type_info({}, {}, {})
- {}
- /*! @brief Default copy constructor. */
- type_info(const type_info &) ENTT_NOEXCEPT = default;
- /*! @brief Default move constructor. */
- type_info(type_info &&) ENTT_NOEXCEPT = default;
- /**
- * @brief Default copy assignment operator.
- * @return This type info object.
- */
- type_info & operator=(const type_info &) ENTT_NOEXCEPT = default;
- /**
- * @brief Default move assignment operator.
- * @return This type info object.
- */
- type_info & operator=(type_info &&) ENTT_NOEXCEPT = default;
- /**
- * @brief Checks if a type info object is properly initialized.
- * @return True if the object is properly initialized, false otherwise.
- */
- [[nodiscard]] explicit operator bool() const ENTT_NOEXCEPT {
- return name_value.data() != nullptr;
- }
- /**
- * @brief Type sequential identifier.
- * @return Type sequential identifier.
- */
- [[nodiscard]] id_type seq() const ENTT_NOEXCEPT {
- return seq_value;
- }
- /**
- * @brief Type hash.
- * @return Type hash.
- */
- [[nodiscard]] id_type hash() const ENTT_NOEXCEPT {
- return hash_value;
- }
- /**
- * @brief Type name.
- * @return Type name.
- */
- [[nodiscard]] std::string_view name() const ENTT_NOEXCEPT {
- return name_value;
- }
- /**
- * @brief Compares the contents of two type info objects.
- * @param other Object with which to compare.
- * @return False if the two contents differ, true otherwise.
- */
- [[nodiscard]] bool operator==(const type_info &other) const ENTT_NOEXCEPT {
- return hash_value == other.hash_value;
- }
- private:
- id_type seq_value;
- id_type hash_value;
- std::string_view name_value;
- };
- /**
- * @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 contents differ, false otherwise.
- */
- [[nodiscard]] inline bool operator!=(const type_info &lhs, const type_info &rhs) ENTT_NOEXCEPT {
- return !(lhs == rhs);
- }
- /**
- * @brief Returns the type info object for a given type.
- * @tparam Type Type for which to generate a type info object.
- * @return The type info object for the given type.
- */
- template<typename Type>
- [[nodiscard]] type_info type_id() ENTT_NOEXCEPT {
- return type_info{
- type_seq<std::remove_cv_t<std::remove_reference_t<Type>>>::value(),
- type_hash<std::remove_cv_t<std::remove_reference_t<Type>>>::value(),
- type_name<std::remove_cv_t<std::remove_reference_t<Type>>>::value()
- };
- }
- }
- #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<class 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_t = 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_v = 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::disjunction_v<std::is_same<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<class 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;
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- namespace internal {
- template<typename>
- [[nodiscard]] constexpr bool is_equality_comparable(...) { return false; }
- template<typename Type>
- [[nodiscard]] constexpr auto is_equality_comparable(choice_t<0>)
- -> decltype(std::declval<Type>() == std::declval<Type>()) { return true; }
- template<typename Type>
- [[nodiscard]] constexpr auto is_equality_comparable(choice_t<1>)
- -> decltype(std::declval<typename Type::value_type>(), std::declval<Type>() == std::declval<Type>()) {
- if constexpr(std::is_same_v<typename Type::value_type, Type>) {
- return is_equality_comparable<Type>(choice<0>);
- } else {
- return is_equality_comparable<typename Type::value_type>(choice<2>);
- }
- }
- template<typename Type>
- [[nodiscard]] constexpr auto is_equality_comparable(choice_t<2>)
- -> decltype(std::declval<typename Type::mapped_type>(), std::declval<Type>() == std::declval<Type>()) {
- return is_equality_comparable<typename Type::key_type>(choice<2>) && is_equality_comparable<typename Type::mapped_type>(choice<2>);
- }
- }
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /**
- * @brief Provides the member constant `value` to true if a given type is
- * equality comparable, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_equality_comparable: std::bool_constant<internal::is_equality_comparable<Type>(choice<2>)> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<class Type>
- inline constexpr bool is_equality_comparable_v = is_equality_comparable<Type>::value;
- /*! @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 {};
- /*! @copydoc is_iterator */
- template<typename Type>
- struct is_iterator<Type, std::void_t<typename std::iterator_traits<Type>::iterator_category>>
- : std::true_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 of the
- * required iterator type, false otherwise.
- * @tparam Type The type to test.
- * @tparam It Required iterator type.
- */
- template<typename Type, typename It, typename = void>
- struct is_iterator_type: std::false_type {};
- /*! @copydoc is_iterator_type */
- template<typename Type, typename It>
- struct is_iterator_type<Type, It, std::enable_if_t<is_iterator_v<Type> && std::is_same_v<Type, It>>>
- : std::true_type
- {};
- /*! @copydoc is_iterator_type */
- template<typename Type, typename It>
- struct is_iterator_type<Type, It, std::enable_if_t<!std::is_same_v<Type, It>, std::void_t<typename It::iterator_type>>>
- : is_iterator_type<Type, typename It::iterator_type>
- {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- * @tparam It Required iterator type.
- */
- template<typename Type, typename It>
- inline constexpr bool is_iterator_type_v = is_iterator_type<Type, It>::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;
- }
- #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, DTOR, COMP, ADDR, CADDR, TYPE };
- 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 &, 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>
- [[nodiscard]] static constexpr policy type_to_policy() {
- if constexpr(std::is_lvalue_reference_v<Type>) {
- if constexpr(std::is_const_v<std::remove_reference_t<Type>>) {
- return policy::CREF;
- } else {
- return policy::REF;
- }
- } else {
- return policy::OWNER;
- }
- }
- template<typename Type>
- [[nodiscard]] static bool compare(const void *lhs, const void *rhs) {
- if constexpr(!std::is_function_v<Type> && is_equality_comparable_v<Type>) {
- return *static_cast<const Type *>(lhs) == *static_cast<const Type *>(rhs);
- } else {
- return lhs == rhs;
- }
- }
- template<typename Type>
- static const void * basic_vtable([[maybe_unused]] const operation op, [[maybe_unused]] const basic_any &from, [[maybe_unused]] void *to) {
- static_assert(std::is_same_v<std::remove_reference_t<std::remove_const_t<Type>>, Type>, "Invalid type");
- if constexpr(!std::is_void_v<Type>) {
- const Type *instance = (in_situ<Type> && from.mode == policy::OWNER)
- ? ENTT_LAUNDER(reinterpret_cast<const Type *>(&from.storage))
- : static_cast<const Type *>(from.instance);
- switch(op) {
- case operation::COPY:
- if constexpr(std::is_copy_constructible_v<Type>) {
- static_cast<basic_any *>(to)->emplace<Type>(*instance);
- }
- break;
- case operation::MOVE:
- if constexpr(in_situ<Type>) {
- if(from.mode == policy::OWNER) {
- return new (&static_cast<basic_any *>(to)->storage) Type{std::move(*const_cast<Type *>(instance))};
- }
- }
- return (static_cast<basic_any *>(to)->instance = std::exchange(const_cast<basic_any &>(from).instance, nullptr));
- case operation::DTOR:
- if(from.mode == policy::OWNER) {
- if constexpr(in_situ<Type>) {
- instance->~Type();
- } else if constexpr(std::is_array_v<Type>) {
- delete[] instance;
- } else {
- delete instance;
- }
- }
- break;
- case operation::COMP:
- return compare<Type>(instance, (*static_cast<const basic_any **>(to))->data()) ? to : nullptr;
- case operation::ADDR:
- if(from.mode == policy::CREF) {
- return nullptr;
- }
- [[fallthrough]];
- case operation::CADDR:
- return instance;
- case operation::TYPE:
- *static_cast<type_info *>(to) = type_id<Type>();
- break;
- }
- }
- return nullptr;
- }
- template<typename Type, typename... Args>
- void initialize([[maybe_unused]] Args &&... args) {
- if constexpr(!std::is_void_v<Type>) {
- if constexpr(std::is_lvalue_reference_v<Type>) {
- static_assert(sizeof...(Args) == 1u && (std::is_lvalue_reference_v<Args> && ...), "Invalid arguments");
- 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()},
- 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. */
- basic_any() ENTT_NOEXCEPT
- : instance{},
- vtable{&basic_vtable<void>},
- 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)
- : instance{},
- vtable{&basic_vtable<std::remove_const_t<std::remove_reference_t<Type>>>},
- mode{type_to_policy<Type>()}
- {
- initialize<Type>(std::forward<Args>(args)...);
- }
- /**
- * @brief Constructs a wrapper that holds an unmanaged object.
- * @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>
- basic_any(std::reference_wrapper<Type> value) ENTT_NOEXCEPT
- : basic_any{}
- {
- // invokes deprecated assignment operator (and avoids issues with vs2017)
- *this = value;
- }
- /**
- * @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)
- : instance{},
- vtable{&basic_vtable<std::decay_t<Type>>},
- mode{policy::OWNER}
- {
- 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)
- : instance{},
- vtable{&basic_vtable<void>},
- mode{policy::OWNER}
- {
- other.vtable(operation::COPY, other, this);
- }
- /**
- * @brief Move constructor.
- * @param other The instance to move from.
- */
- basic_any(basic_any &&other) ENTT_NOEXCEPT
- : instance{},
- vtable{other.vtable},
- mode{other.mode}
- {
- vtable(operation::MOVE, other, this);
- }
- /*! @brief Frees the internal storage, whatever it means. */
- ~basic_any() {
- vtable(operation::DTOR, *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();
- 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 {
- std::exchange(vtable, other.vtable)(operation::DTOR, *this, nullptr);
- other.vtable(operation::MOVE, other, this);
- 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>
- [[deprecated("Use std::in_place_type<T &>, entt::make_any<T &>, emplace<Type &> or forward_as_any instead")]]
- basic_any & operator=(std::reference_wrapper<Type> value) ENTT_NOEXCEPT {
- emplace<Type &>(value.get());
- 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 type of the contained object.
- * @return The type of the contained object, if any.
- */
- [[nodiscard]] type_info type() const ENTT_NOEXCEPT {
- type_info info{};
- vtable(operation::TYPE, *this, &info);
- 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(operation::CADDR, *this, nullptr);
- }
- /*! @copydoc data */
- [[nodiscard]] void * data() ENTT_NOEXCEPT {
- return const_cast<void *>(vtable(operation::ADDR, *this, 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) {
- std::exchange(vtable, &basic_vtable<std::remove_const_t<std::remove_reference_t<Type>>>)(operation::DTOR, *this, nullptr);
- mode = type_to_policy<Type>();
- initialize<Type>(std::forward<Args>(args)...);
- }
- /*! @brief Destroys contained object */
- void reset() {
- std::exchange(vtable, &basic_vtable<void>)(operation::DTOR, *this, 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(operation::CADDR, *this, nullptr) == 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 {
- const basic_any *trampoline = &other;
- return type() == other.type() && (vtable(operation::COMP, *this, &trampoline) || !other.data());
- }
- /**
- * @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; };
- 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 {
- // 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>(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 {
- return (data->type() == type_id<Type>() ? static_cast<const Type *>(data->data()) : nullptr);
- }
- /*! @copydoc any_cast */
- template<typename Type, std::size_t Len, std::size_t Align>
- Type * any_cast(basic_any<Len, Align> *data) ENTT_NOEXCEPT {
- // last attempt to make wrappers for const references return their values
- return (data->type() == type_id<Type>() ? static_cast<Type *>(static_cast<constness_as_t<basic_any<Len, Align>, Type> *>(data)->data()) : nullptr);
- }
- /**
- * @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)};
- }
- }
- #endif
- // #include "../core/fwd.hpp"
- // #include "../core/type_info.hpp"
- #ifndef ENTT_CORE_TYPE_INFO_HPP
- #define ENTT_CORE_TYPE_INFO_HPP
- #include <string_view>
- #include <type_traits>
- // #include "../config/config.h"
- // #include "../core/attribute.h"
- // #include "hashed_string.hpp"
- // #include "fwd.hpp"
- namespace entt {
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- namespace internal {
- struct ENTT_API type_seq 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;
- }
- }
- /**
- * 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_seq 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_seq::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_seq<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. */
- class type_info final {
- template<typename>
- friend type_info type_id() ENTT_NOEXCEPT;
- type_info(id_type seq_v, id_type hash_v, std::string_view name_v) ENTT_NOEXCEPT
- : seq_value{seq_v},
- hash_value{hash_v},
- name_value{name_v}
- {}
- public:
- /*! @brief Default constructor. */
- type_info() ENTT_NOEXCEPT
- : type_info({}, {}, {})
- {}
- /*! @brief Default copy constructor. */
- type_info(const type_info &) ENTT_NOEXCEPT = default;
- /*! @brief Default move constructor. */
- type_info(type_info &&) ENTT_NOEXCEPT = default;
- /**
- * @brief Default copy assignment operator.
- * @return This type info object.
- */
- type_info & operator=(const type_info &) ENTT_NOEXCEPT = default;
- /**
- * @brief Default move assignment operator.
- * @return This type info object.
- */
- type_info & operator=(type_info &&) ENTT_NOEXCEPT = default;
- /**
- * @brief Checks if a type info object is properly initialized.
- * @return True if the object is properly initialized, false otherwise.
- */
- [[nodiscard]] explicit operator bool() const ENTT_NOEXCEPT {
- return name_value.data() != nullptr;
- }
- /**
- * @brief Type sequential identifier.
- * @return Type sequential identifier.
- */
- [[nodiscard]] id_type seq() const ENTT_NOEXCEPT {
- return seq_value;
- }
- /**
- * @brief Type hash.
- * @return Type hash.
- */
- [[nodiscard]] id_type hash() const ENTT_NOEXCEPT {
- return hash_value;
- }
- /**
- * @brief Type name.
- * @return Type name.
- */
- [[nodiscard]] std::string_view name() const ENTT_NOEXCEPT {
- return name_value;
- }
- /**
- * @brief Compares the contents of two type info objects.
- * @param other Object with which to compare.
- * @return False if the two contents differ, true otherwise.
- */
- [[nodiscard]] bool operator==(const type_info &other) const ENTT_NOEXCEPT {
- return hash_value == other.hash_value;
- }
- private:
- id_type seq_value;
- id_type hash_value;
- std::string_view name_value;
- };
- /**
- * @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 contents differ, false otherwise.
- */
- [[nodiscard]] inline bool operator!=(const type_info &lhs, const type_info &rhs) ENTT_NOEXCEPT {
- return !(lhs == rhs);
- }
- /**
- * @brief Returns the type info object for a given type.
- * @tparam Type Type for which to generate a type info object.
- * @return The type info object for the given type.
- */
- template<typename Type>
- [[nodiscard]] type_info type_id() ENTT_NOEXCEPT {
- return type_info{
- type_seq<std::remove_cv_t<std::remove_reference_t<Type>>>::value(),
- type_hash<std::remove_cv_t<std::remove_reference_t<Type>>>::value(),
- type_name<std::remove_cv_t<std::remove_reference_t<Type>>>::value()
- };
- }
- }
- #endif
- // #include "../core/type_traits.hpp"
- // #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 <utility>
- #include <type_traits>
- // #include "../config/config.h"
- // #include "../core/type_traits.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...>
- 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 Exclude Types of components used to filter the group.
- * @tparam Get Type of components observed by the group.
- */
- template<typename Entity, typename... Exclude, typename... Get>
- class basic_group<Entity, exclude_t<Exclude...>, get_t<Get...>> final {
- /*! @brief A registry is allowed to create groups. */
- friend class basic_registry<Entity>;
- using basic_common_type = basic_sparse_set<Entity>;
- template<typename Component>
- using storage_type = constness_as_t<typename storage_traits<Entity, std::remove_const_t<Component>>::storage_type, Component>;
- class iterable final {
- template<typename It>
- struct iterable_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 = void;
- using reference = value_type;
- using iterator_category = std::input_iterator_tag;
- template<typename... Args>
- iterable_iterator(It from, const std::tuple<storage_type<Get> *...> &args) ENTT_NOEXCEPT
- : it{from},
- pools{args}
- {}
- iterable_iterator & operator++() ENTT_NOEXCEPT {
- return ++it, *this;
- }
- iterable_iterator operator++(int) ENTT_NOEXCEPT {
- iterable_iterator orig = *this;
- return ++(*this), orig;
- }
- [[nodiscard]] reference operator*() const ENTT_NOEXCEPT {
- const auto entt = *it;
- return std::tuple_cat(std::make_tuple(entt), get_as_tuple(*std::get<storage_type<Get> *>(pools), entt)...);
- }
- [[nodiscard]] bool operator==(const iterable_iterator &other) const ENTT_NOEXCEPT {
- return other.it == it;
- }
- [[nodiscard]] bool operator!=(const iterable_iterator &other) const ENTT_NOEXCEPT {
- return !(*this == other);
- }
- private:
- It it;
- std::tuple<storage_type<Get> *...> pools;
- };
- public:
- using iterator = iterable_iterator<typename basic_common_type::iterator>;
- using reverse_iterator = iterable_iterator<typename basic_common_type::reverse_iterator>;
- iterable(basic_common_type * const ref, const std::tuple<storage_type<Get> *...> &cpools)
- : handler{ref},
- pools{cpools}
- {}
- [[nodiscard]] iterator begin() const ENTT_NOEXCEPT {
- return handler ? iterator{handler->begin(), pools} : iterator{{}, pools};
- }
- [[nodiscard]] iterator end() const ENTT_NOEXCEPT {
- return handler ? iterator{handler->end(), pools} : iterator{{}, pools};
- }
- [[nodiscard]] reverse_iterator rbegin() const ENTT_NOEXCEPT {
- return handler ? reverse_iterator{handler->rbegin(), pools} : reverse_iterator{{}, pools};
- }
- [[nodiscard]] reverse_iterator rend() const ENTT_NOEXCEPT {
- return handler ? reverse_iterator{handler->rend(), pools} : reverse_iterator{{}, pools};
- }
- private:
- basic_common_type * const handler;
- const 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 Random access iterator type. */
- using iterator = typename basic_common_type::iterator;
- /*! @brief Reversed iterator type. */
- using reverse_iterator = typename basic_common_type::reverse_iterator;
- /*! @brief Iterable group type. */
- using iterable_group = iterable;
- /*! @brief Default constructor to use to create empty, invalid groups. */
- basic_group() ENTT_NOEXCEPT
- : handler{}
- {}
- /**
- * @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 Direct access to the list of entities.
- *
- * The returned pointer is such that range `[data(), data() + size())` is
- * always a valid range, even if the container is empty.
- *
- * @return A pointer to the array of entities.
- */
- [[nodiscard]] auto data() const ENTT_NOEXCEPT {
- return *this ? handler->data() : nullptr;
- }
- /**
- * @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 {
- 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 {
- const auto it = rbegin();
- return it != rend() ? *it : null;
- }
- /**
- * @brief Finds an entity.
- * @param entt A valid entity 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 {
- 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 entity identifier.
- * @return True if the group contains the given entity, false otherwise.
- */
- [[nodiscard]] bool contains(const entity_type entt) const {
- 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 Component Types of components to get.
- * @param entt A valid entity identifier.
- * @return The components assigned to the entity.
- */
- template<typename... Component>
- [[nodiscard]] decltype(auto) get(const entity_type entt) const {
- ENTT_ASSERT(contains(entt), "Group does not contain entity");
- if constexpr(sizeof...(Component) == 0) {
- return std::tuple_cat(get_as_tuple(*std::get<storage_type<Get> *>(pools), entt)...);
- } else if constexpr(sizeof...(Component) == 1) {
- return (std::get<storage_type<Component> *>(pools)->get(entt), ...);
- } else {
- return std::tuple_cat(get_as_tuple(*std::get<storage_type<Component> *>(pools), 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_ the 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_group each() const ENTT_NOEXCEPT {
- return iterable_group{handler, 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 oject 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 Component 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... Component, typename Compare, typename Sort = std_sort, typename... Args>
- void sort(Compare compare, Sort algo = Sort{}, Args &&... args) {
- if(*this) {
- if constexpr(sizeof...(Component) == 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 if constexpr(sizeof...(Component) == 1) {
- handler->sort([this, compare = std::move(compare)](const entity_type lhs, const entity_type rhs) {
- return compare((std::get<storage_type<Component> *>(pools)->get(lhs), ...), (std::get<storage_type<Component> *>(pools)->get(rhs), ...));
- }, std::move(algo), std::forward<Args>(args)...);
- } else {
- handler->sort([this, compare = std::move(compare)](const entity_type lhs, const entity_type rhs) {
- return compare(std::forward_as_tuple(std::get<storage_type<Component> *>(pools)->get(lhs)...), std::forward_as_tuple(std::get<storage_type<Component> *>(pools)->get(rhs)...));
- }, 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 Component Type of component to use to impose the order.
- */
- template<typename Component>
- void sort() const {
- if(*this) {
- handler->respect(*std::get<storage_type<Component> *>(pools));
- }
- }
- private:
- basic_common_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 Exclude Types of components used to filter the group.
- * @tparam Get Types of components observed by the group.
- * @tparam Owned Types of components owned by the group.
- */
- template<typename Entity, typename... Exclude, typename... Get, typename... Owned>
- class basic_group<Entity, exclude_t<Exclude...>, get_t<Get...>, Owned...> final {
- /*! @brief A registry is allowed to create groups. */
- friend class basic_registry<Entity>;
- using basic_common_type = basic_sparse_set<Entity>;
- template<typename Component>
- using storage_type = constness_as_t<typename storage_traits<Entity, std::remove_const_t<Component>>::storage_type, Component>;
- class iterable final {
- template<typename, typename>
- struct iterable_iterator;
- template<typename It, typename... OIt>
- struct iterable_iterator<It, type_list<OIt...>> final {
- using difference_type = std::ptrdiff_t;
- using value_type = decltype(std::tuple_cat(std::tuple<Entity>{}, std::declval<basic_group>().get({})));
- using pointer = void;
- using reference = value_type;
- using iterator_category = std::input_iterator_tag;
- template<typename... Other>
- iterable_iterator(It from, const std::tuple<Other...> &other, const std::tuple<storage_type<Get> *...> &cpools) ENTT_NOEXCEPT
- : it{from},
- owned{std::get<OIt>(other)...},
- get{cpools}
- {}
- iterable_iterator & operator++() ENTT_NOEXCEPT {
- return ++it, (++std::get<OIt>(owned), ...), *this;
- }
- iterable_iterator operator++(int) ENTT_NOEXCEPT {
- iterable_iterator orig = *this;
- return ++(*this), orig;
- }
- [[nodiscard]] reference operator*() const ENTT_NOEXCEPT {
- return std::tuple_cat(
- std::make_tuple(*it),
- std::forward_as_tuple(*std::get<OIt>(owned)...),
- get_as_tuple(*std::get<storage_type<Get> *>(get), *it)...
- );
- }
- [[nodiscard]] bool operator==(const iterable_iterator &other) const ENTT_NOEXCEPT {
- return other.it == it;
- }
- [[nodiscard]] bool operator!=(const iterable_iterator &other) const ENTT_NOEXCEPT {
- return !(*this == other);
- }
- private:
- It it;
- std::tuple<OIt...> owned;
- std::tuple<storage_type<Get> *...> get;
- };
- public:
- using iterator = iterable_iterator<
- typename basic_common_type::iterator,
- type_list_cat_t<std::conditional_t<std::is_void_v<decltype(std::declval<storage_type<Owned>>().get({}))>, type_list<>, type_list<decltype(std::declval<storage_type<Owned>>().end())>>...>
- >;
- using reverse_iterator = iterable_iterator<
- typename basic_common_type::reverse_iterator,
- type_list_cat_t<std::conditional_t<std::is_void_v<decltype(std::declval<storage_type<Owned>>().get({}))>, type_list<>, type_list<decltype(std::declval<storage_type<Owned>>().rbegin())>>...>
- >;
- iterable(std::tuple<storage_type<Owned> *..., storage_type<Get> *...> cpools, const std::size_t * const extent)
- : pools{cpools},
- length{extent}
- {}
- [[nodiscard]] iterator begin() const ENTT_NOEXCEPT {
- return length ? iterator{
- std::get<0>(pools)->basic_common_type::end() - *length,
- std::make_tuple((std::get<storage_type<Owned> *>(pools)->end() - *length)...),
- std::make_tuple(std::get<storage_type<Get> *>(pools)...)
- } : iterator{{}, std::make_tuple(decltype(std::get<storage_type<Owned> *>(pools)->end()){}...), std::make_tuple(std::get<storage_type<Get> *>(pools)...)};
- }
- [[nodiscard]] iterator end() const ENTT_NOEXCEPT {
- return length ? iterator{
- std::get<0>(pools)->basic_common_type::end(),
- std::make_tuple((std::get<storage_type<Owned> *>(pools)->end())...),
- std::make_tuple(std::get<storage_type<Get> *>(pools)...)
- } : iterator{{}, std::make_tuple(decltype(std::get<storage_type<Owned> *>(pools)->end()){}...), std::make_tuple(std::get<storage_type<Get> *>(pools)...)};
- }
- [[nodiscard]] reverse_iterator rbegin() const ENTT_NOEXCEPT {
- return length ? reverse_iterator{
- std::get<0>(pools)->basic_common_type::rbegin(),
- std::make_tuple((std::get<storage_type<Owned> *>(pools)->rbegin())...),
- std::make_tuple(std::get<storage_type<Get> *>(pools)...)
- } : reverse_iterator{{}, std::make_tuple(decltype(std::get<storage_type<Owned> *>(pools)->rbegin()){}...), std::make_tuple(std::get<storage_type<Get> *>(pools)...)};
- }
- [[nodiscard]] reverse_iterator rend() const ENTT_NOEXCEPT {
- return length ? reverse_iterator{
- std::get<0>(pools)->basic_common_type::rbegin() + *length,
- std::make_tuple((std::get<storage_type<Owned> *>(pools)->rbegin() + *length)...),
- std::make_tuple(std::get<storage_type<Get> *>(pools)...)
- } : reverse_iterator{{}, std::make_tuple(decltype(std::get<storage_type<Owned> *>(pools)->rbegin()){}...), std::make_tuple(std::get<storage_type<Get> *>(pools)...)};
- }
- private:
- const std::tuple<storage_type<Owned> *..., storage_type<Get> *...> pools;
- const std::size_t * const length;
- };
- 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 Random access iterator type. */
- using iterator = typename basic_common_type::iterator;
- /*! @brief Reversed iterator type. */
- using reverse_iterator = typename basic_common_type::reverse_iterator;
- /*! @brief Iterable group type. */
- using iterable_group = iterable;
- /*! @brief Default constructor to use to create empty, invalid groups. */
- basic_group() ENTT_NOEXCEPT
- : length{}
- {}
- /**
- * @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 Direct access to the raw representation offered by the storage.
- *
- * @warning
- * This function is only available for owned types.
- *
- * @tparam Component Type of component in which one is interested.
- * @return A pointer to the array of components.
- */
- template<typename Component>
- [[nodiscard]] auto raw() const ENTT_NOEXCEPT {
- static_assert((std::is_same_v<Component, Owned> || ...), "Non-owned type");
- auto *cpool = std::get<storage_type<Component> *>(pools);
- return cpool ? cpool->raw() : decltype(cpool->raw()){};
- }
- /**
- * @brief Direct access to the list of entities.
- *
- * The returned pointer is such that range `[data(), data() + size())` is
- * always a valid range, even if the container is empty.
- *
- * @return A pointer to the array of entities.
- */
- [[nodiscard]] auto data() const ENTT_NOEXCEPT {
- return *this ? std::get<0>(pools)->data() : nullptr;
- }
- /**
- * @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)->basic_common_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)->basic_common_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)->basic_common_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)->basic_common_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 {
- 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 {
- const auto it = rbegin();
- return it != rend() ? *it : null;
- }
- /**
- * @brief Finds an entity.
- * @param entt A valid entity 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 {
- 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 entity identifier.
- * @return True if the group contains the given entity, false otherwise.
- */
- [[nodiscard]] bool contains(const entity_type entt) const {
- 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 Component Types of components to get.
- * @param entt A valid entity identifier.
- * @return The components assigned to the entity.
- */
- template<typename... Component>
- [[nodiscard]] decltype(auto) get(const entity_type entt) const {
- ENTT_ASSERT(contains(entt), "Group does not contain entity");
- if constexpr(sizeof...(Component) == 0) {
- return std::tuple_cat(get_as_tuple(*std::get<storage_type<Owned> *>(pools), entt)..., get_as_tuple(*std::get<storage_type<Get> *>(pools), entt)...);
- } else if constexpr(sizeof...(Component) == 1) {
- return (std::get<storage_type<Component> *>(pools)->get(entt), ...);
- } else {
- return std::tuple_cat(get_as_tuple(*std::get<storage_type<Component> *>(pools), 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_ the 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_group each() const ENTT_NOEXCEPT {
- return iterable_group{pools, length};
- }
- /**
- * @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 oject 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 Component 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... Component, 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...(Component) == 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 if constexpr(sizeof...(Component) == 1) {
- cpool->sort_n(*length, [this, compare = std::move(compare)](const entity_type lhs, const entity_type rhs) {
- return compare((std::get<storage_type<Component> *>(pools)->get(lhs), ...), (std::get<storage_type<Component> *>(pools)->get(rhs), ...));
- }, std::move(algo), std::forward<Args>(args)...);
- } else {
- cpool->sort_n(*length, [this, compare = std::move(compare)](const entity_type lhs, const entity_type rhs) {
- return compare(std::forward_as_tuple(std::get<storage_type<Component> *>(pools)->get(lhs)...), std::forward_as_tuple(std::get<storage_type<Component> *>(pools)->get(rhs)...));
- }, 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(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;
- };
- }
- #endif
- // #include "poly_storage.hpp"
- #ifndef ENTT_ENTITY_POLY_STORAGE_HPP
- #define ENTT_ENTITY_POLY_STORAGE_HPP
- #include <cstddef>
- #include <tuple>
- // #include "../core/type_info.hpp"
- // #include "../core/type_traits.hpp"
- // #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
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_NOEXCEPT noexcept
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_NOEXCEPT
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606L
- # include <new>
- # define ENTT_LAUNDER(expr) std::launder(expr)
- #else
- # define ENTT_LAUNDER(expr) expr
- #endif
- #ifndef ENTT_USE_ATOMIC
- # define ENTT_MAYBE_ATOMIC(Type) Type
- #else
- # include <atomic>
- # define ENTT_MAYBE_ATOMIC(Type) std::atomic<Type>
- #endif
- #ifndef ENTT_ID_TYPE
- # include <cstdint>
- # define ENTT_ID_TYPE std::uint32_t
- #endif
- #ifdef ENTT_SPARSE_PAGE
- static_assert(ENTT_SPARSE_PAGE && ((ENTT_SPARSE_PAGE & (ENTT_SPARSE_PAGE - 1)) == 0), "ENTT_SPARSE_PAGE must be a power of two");
- #else
- # define ENTT_SPARSE_PAGE 4096
- #endif
- #ifdef ENTT_PACKED_PAGE
- static_assert(ENTT_PACKED_PAGE && ((ENTT_PACKED_PAGE & (ENTT_PACKED_PAGE - 1)) == 0), "ENTT_PACKED_PAGE must be a power of two");
- #else
- # 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
- # include <type_traits>
- # define ENTT_IGNORE_IF_EMPTY std::false_type
- #else
- # include <type_traits>
- # define ENTT_IGNORE_IF_EMPTY std::true_type
- #endif
- #ifndef ENTT_STANDARD_CPP
- # 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
- #endif
- // #include "../core/any.hpp"
- #ifndef ENTT_CORE_ANY_HPP
- #define ENTT_CORE_ANY_HPP
- #include <cstddef>
- #include <functional>
- #include <memory>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- #ifndef ENTT_CONFIG_CONFIG_H
- #define ENTT_CONFIG_CONFIG_H
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_NOEXCEPT noexcept
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_NOEXCEPT
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606L
- # include <new>
- # define ENTT_LAUNDER(expr) std::launder(expr)
- #else
- # define ENTT_LAUNDER(expr) expr
- #endif
- #ifndef ENTT_USE_ATOMIC
- # define ENTT_MAYBE_ATOMIC(Type) Type
- #else
- # include <atomic>
- # define ENTT_MAYBE_ATOMIC(Type) std::atomic<Type>
- #endif
- #ifndef ENTT_ID_TYPE
- # include <cstdint>
- # define ENTT_ID_TYPE std::uint32_t
- #endif
- #ifdef ENTT_SPARSE_PAGE
- static_assert(ENTT_SPARSE_PAGE && ((ENTT_SPARSE_PAGE & (ENTT_SPARSE_PAGE - 1)) == 0), "ENTT_SPARSE_PAGE must be a power of two");
- #else
- # define ENTT_SPARSE_PAGE 4096
- #endif
- #ifdef ENTT_PACKED_PAGE
- static_assert(ENTT_PACKED_PAGE && ((ENTT_PACKED_PAGE & (ENTT_PACKED_PAGE - 1)) == 0), "ENTT_PACKED_PAGE must be a power of two");
- #else
- # 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
- # include <type_traits>
- # define ENTT_IGNORE_IF_EMPTY std::false_type
- #else
- # include <type_traits>
- # define ENTT_IGNORE_IF_EMPTY std::true_type
- #endif
- #ifndef ENTT_STANDARD_CPP
- # 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
- #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
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_NOEXCEPT noexcept
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_NOEXCEPT
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606L
- # include <new>
- # define ENTT_LAUNDER(expr) std::launder(expr)
- #else
- # define ENTT_LAUNDER(expr) expr
- #endif
- #ifndef ENTT_USE_ATOMIC
- # define ENTT_MAYBE_ATOMIC(Type) Type
- #else
- # include <atomic>
- # define ENTT_MAYBE_ATOMIC(Type) std::atomic<Type>
- #endif
- #ifndef ENTT_ID_TYPE
- # include <cstdint>
- # define ENTT_ID_TYPE std::uint32_t
- #endif
- #ifdef ENTT_SPARSE_PAGE
- static_assert(ENTT_SPARSE_PAGE && ((ENTT_SPARSE_PAGE & (ENTT_SPARSE_PAGE - 1)) == 0), "ENTT_SPARSE_PAGE must be a power of two");
- #else
- # define ENTT_SPARSE_PAGE 4096
- #endif
- #ifdef ENTT_PACKED_PAGE
- static_assert(ENTT_PACKED_PAGE && ((ENTT_PACKED_PAGE & (ENTT_PACKED_PAGE - 1)) == 0), "ENTT_PACKED_PAGE must be a power of two");
- #else
- # 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
- # include <type_traits>
- # define ENTT_IGNORE_IF_EMPTY std::false_type
- #else
- # include <type_traits>
- # define ENTT_IGNORE_IF_EMPTY std::true_type
- #endif
- #ifndef ENTT_STANDARD_CPP
- # 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
- #endif
- namespace entt {
- /*! @brief Identity function object (waiting for C++20). */
- struct identity {
- /**
- * @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;
- };
- }
- #endif
- // #include "fwd.hpp"
- #ifndef ENTT_CORE_FWD_HPP
- #define ENTT_CORE_FWD_HPP
- #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<>;
- }
- #endif
- // #include "type_info.hpp"
- #ifndef ENTT_CORE_TYPE_INFO_HPP
- #define ENTT_CORE_TYPE_INFO_HPP
- #include <string_view>
- #include <type_traits>
- // #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 "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;
- };
- }
- /**
- * 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 identifers 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.
- *
- * @tparam Char Character type.
- */
- template<typename Char>
- class basic_hashed_string {
- using traits_type = internal::fnv1a_traits<id_type>;
- struct const_wrapper {
- // non-explicit constructor on purpose
- constexpr const_wrapper(const Char *curr) ENTT_NOEXCEPT: str{curr} {}
- const Char *str;
- };
- // Fowler–Noll–Vo hash function v. 1a - the good
- [[nodiscard]] static constexpr id_type helper(const Char *curr) ENTT_NOEXCEPT {
- auto value = traits_type::offset;
- while(*curr != 0) {
- value = (value ^ static_cast<traits_type::type>(*(curr++))) * traits_type::prime;
- }
- return value;
- }
- public:
- /*! @brief Character type. */
- using value_type = Char;
- /*! @brief Unsigned integer type. */
- using hash_type = id_type;
- /**
- * @brief Returns directly the numeric representation of a string view.
- * @param str Human-readable identifer.
- * @param size Length of the string to hash.
- * @return The numeric representation of the string.
- */
- [[nodiscard]] static constexpr hash_type value(const value_type *str, std::size_t size) ENTT_NOEXCEPT {
- id_type partial{traits_type::offset};
- while(size--) { partial = (partial^(str++)[0])*traits_type::prime; }
- return partial;
- }
- /**
- * @brief Returns directly the numeric representation of a string.
- *
- * Forcing template resolution avoids implicit conversions. An
- * human-readable identifier can be anything but a plain, old bunch of
- * characters.<br/>
- * Example of use:
- * @code{.cpp}
- * const auto value = basic_hashed_string<char>::to_value("my.png");
- * @endcode
- *
- * @tparam N Number of characters of the identifier.
- * @param str Human-readable identifer.
- * @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 helper(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 hash_type value(const_wrapper wrapper) ENTT_NOEXCEPT {
- return helper(wrapper.str);
- }
- /*! @brief Constructs an empty hashed string. */
- constexpr basic_hashed_string() ENTT_NOEXCEPT
- : str{nullptr}, hash{}
- {}
- /**
- * @brief Constructs a hashed string from an array of const characters.
- *
- * Forcing template resolution avoids implicit conversions. An
- * human-readable identifier can be anything but a plain, old bunch of
- * characters.<br/>
- * Example of use:
- * @code{.cpp}
- * basic_hashed_string<char> hs{"my.png"};
- * @endcode
- *
- * @tparam N Number of characters of the identifier.
- * @param curr Human-readable identifer.
- */
- template<std::size_t N>
- constexpr basic_hashed_string(const value_type (&curr)[N]) ENTT_NOEXCEPT
- : str{curr}, hash{helper(curr)}
- {}
- /**
- * @brief Explicit constructor on purpose to avoid constructing a hashed
- * string directly from a `const value_type *`.
- * @param wrapper Helps achieving the purpose by relying on overloading.
- */
- explicit constexpr basic_hashed_string(const_wrapper wrapper) ENTT_NOEXCEPT
- : str{wrapper.str}, hash{helper(wrapper.str)}
- {}
- /**
- * @brief Returns the human-readable representation of a hashed string.
- * @return The string used to initialize the instance.
- */
- [[nodiscard]] constexpr const value_type * data() const ENTT_NOEXCEPT {
- return str;
- }
- /**
- * @brief Returns the numeric representation of a hashed string.
- * @return The numeric representation of the instance.
- */
- [[nodiscard]] constexpr hash_type value() const ENTT_NOEXCEPT {
- return 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 instance.
- */
- [[nodiscard]] constexpr operator hash_type() const ENTT_NOEXCEPT { return value(); }
- /**
- * @brief Compares two hashed strings.
- * @param other Hashed string with which to compare.
- * @return True if the two hashed strings are identical, false otherwise.
- */
- [[nodiscard]] constexpr bool operator==(const basic_hashed_string &other) const ENTT_NOEXCEPT {
- return hash == other.hash;
- }
- private:
- const value_type *str;
- hash_type hash;
- };
- /**
- * @brief Deduction guide.
- *
- * It allows to deduce the character type of the hashed string directly from a
- * human-readable identifer provided to the constructor.
- *
- * @tparam Char Character type.
- * @tparam N Number of characters of the identifier.
- * @param str Human-readable identifer.
- */
- 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 == 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 entt::hashed_string operator"" _hs(const char *str, std::size_t) ENTT_NOEXCEPT {
- return entt::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 entt::hashed_wstring operator"" _hws(const wchar_t *str, std::size_t) ENTT_NOEXCEPT {
- return entt::hashed_wstring{str};
- }
- }
- }
- #endif
- // #include "fwd.hpp"
- namespace entt {
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- namespace internal {
- struct ENTT_API type_seq 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;
- }
- }
- /**
- * 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_seq 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_seq::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_seq<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. */
- class type_info final {
- template<typename>
- friend type_info type_id() ENTT_NOEXCEPT;
- type_info(id_type seq_v, id_type hash_v, std::string_view name_v) ENTT_NOEXCEPT
- : seq_value{seq_v},
- hash_value{hash_v},
- name_value{name_v}
- {}
- public:
- /*! @brief Default constructor. */
- type_info() ENTT_NOEXCEPT
- : type_info({}, {}, {})
- {}
- /*! @brief Default copy constructor. */
- type_info(const type_info &) ENTT_NOEXCEPT = default;
- /*! @brief Default move constructor. */
- type_info(type_info &&) ENTT_NOEXCEPT = default;
- /**
- * @brief Default copy assignment operator.
- * @return This type info object.
- */
- type_info & operator=(const type_info &) ENTT_NOEXCEPT = default;
- /**
- * @brief Default move assignment operator.
- * @return This type info object.
- */
- type_info & operator=(type_info &&) ENTT_NOEXCEPT = default;
- /**
- * @brief Checks if a type info object is properly initialized.
- * @return True if the object is properly initialized, false otherwise.
- */
- [[nodiscard]] explicit operator bool() const ENTT_NOEXCEPT {
- return name_value.data() != nullptr;
- }
- /**
- * @brief Type sequential identifier.
- * @return Type sequential identifier.
- */
- [[nodiscard]] id_type seq() const ENTT_NOEXCEPT {
- return seq_value;
- }
- /**
- * @brief Type hash.
- * @return Type hash.
- */
- [[nodiscard]] id_type hash() const ENTT_NOEXCEPT {
- return hash_value;
- }
- /**
- * @brief Type name.
- * @return Type name.
- */
- [[nodiscard]] std::string_view name() const ENTT_NOEXCEPT {
- return name_value;
- }
- /**
- * @brief Compares the contents of two type info objects.
- * @param other Object with which to compare.
- * @return False if the two contents differ, true otherwise.
- */
- [[nodiscard]] bool operator==(const type_info &other) const ENTT_NOEXCEPT {
- return hash_value == other.hash_value;
- }
- private:
- id_type seq_value;
- id_type hash_value;
- std::string_view name_value;
- };
- /**
- * @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 contents differ, false otherwise.
- */
- [[nodiscard]] inline bool operator!=(const type_info &lhs, const type_info &rhs) ENTT_NOEXCEPT {
- return !(lhs == rhs);
- }
- /**
- * @brief Returns the type info object for a given type.
- * @tparam Type Type for which to generate a type info object.
- * @return The type info object for the given type.
- */
- template<typename Type>
- [[nodiscard]] type_info type_id() ENTT_NOEXCEPT {
- return type_info{
- type_seq<std::remove_cv_t<std::remove_reference_t<Type>>>::value(),
- type_hash<std::remove_cv_t<std::remove_reference_t<Type>>>::value(),
- type_name<std::remove_cv_t<std::remove_reference_t<Type>>>::value()
- };
- }
- }
- #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<class 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_t = 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_v = 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::disjunction_v<std::is_same<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<class 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;
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- namespace internal {
- template<typename>
- [[nodiscard]] constexpr bool is_equality_comparable(...) { return false; }
- template<typename Type>
- [[nodiscard]] constexpr auto is_equality_comparable(choice_t<0>)
- -> decltype(std::declval<Type>() == std::declval<Type>()) { return true; }
- template<typename Type>
- [[nodiscard]] constexpr auto is_equality_comparable(choice_t<1>)
- -> decltype(std::declval<typename Type::value_type>(), std::declval<Type>() == std::declval<Type>()) {
- if constexpr(std::is_same_v<typename Type::value_type, Type>) {
- return is_equality_comparable<Type>(choice<0>);
- } else {
- return is_equality_comparable<typename Type::value_type>(choice<2>);
- }
- }
- template<typename Type>
- [[nodiscard]] constexpr auto is_equality_comparable(choice_t<2>)
- -> decltype(std::declval<typename Type::mapped_type>(), std::declval<Type>() == std::declval<Type>()) {
- return is_equality_comparable<typename Type::key_type>(choice<2>) && is_equality_comparable<typename Type::mapped_type>(choice<2>);
- }
- }
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /**
- * @brief Provides the member constant `value` to true if a given type is
- * equality comparable, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_equality_comparable: std::bool_constant<internal::is_equality_comparable<Type>(choice<2>)> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<class Type>
- inline constexpr bool is_equality_comparable_v = is_equality_comparable<Type>::value;
- /*! @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 {};
- /*! @copydoc is_iterator */
- template<typename Type>
- struct is_iterator<Type, std::void_t<typename std::iterator_traits<Type>::iterator_category>>
- : std::true_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 of the
- * required iterator type, false otherwise.
- * @tparam Type The type to test.
- * @tparam It Required iterator type.
- */
- template<typename Type, typename It, typename = void>
- struct is_iterator_type: std::false_type {};
- /*! @copydoc is_iterator_type */
- template<typename Type, typename It>
- struct is_iterator_type<Type, It, std::enable_if_t<is_iterator_v<Type> && std::is_same_v<Type, It>>>
- : std::true_type
- {};
- /*! @copydoc is_iterator_type */
- template<typename Type, typename It>
- struct is_iterator_type<Type, It, std::enable_if_t<!std::is_same_v<Type, It>, std::void_t<typename It::iterator_type>>>
- : is_iterator_type<Type, typename It::iterator_type>
- {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- * @tparam It Required iterator type.
- */
- template<typename Type, typename It>
- inline constexpr bool is_iterator_type_v = is_iterator_type<Type, It>::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;
- }
- #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, DTOR, COMP, ADDR, CADDR, TYPE };
- 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 &, 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>
- [[nodiscard]] static constexpr policy type_to_policy() {
- if constexpr(std::is_lvalue_reference_v<Type>) {
- if constexpr(std::is_const_v<std::remove_reference_t<Type>>) {
- return policy::CREF;
- } else {
- return policy::REF;
- }
- } else {
- return policy::OWNER;
- }
- }
- template<typename Type>
- [[nodiscard]] static bool compare(const void *lhs, const void *rhs) {
- if constexpr(!std::is_function_v<Type> && is_equality_comparable_v<Type>) {
- return *static_cast<const Type *>(lhs) == *static_cast<const Type *>(rhs);
- } else {
- return lhs == rhs;
- }
- }
- template<typename Type>
- static const void * basic_vtable([[maybe_unused]] const operation op, [[maybe_unused]] const basic_any &from, [[maybe_unused]] void *to) {
- static_assert(std::is_same_v<std::remove_reference_t<std::remove_const_t<Type>>, Type>, "Invalid type");
- if constexpr(!std::is_void_v<Type>) {
- const Type *instance = (in_situ<Type> && from.mode == policy::OWNER)
- ? ENTT_LAUNDER(reinterpret_cast<const Type *>(&from.storage))
- : static_cast<const Type *>(from.instance);
- switch(op) {
- case operation::COPY:
- if constexpr(std::is_copy_constructible_v<Type>) {
- static_cast<basic_any *>(to)->emplace<Type>(*instance);
- }
- break;
- case operation::MOVE:
- if constexpr(in_situ<Type>) {
- if(from.mode == policy::OWNER) {
- return new (&static_cast<basic_any *>(to)->storage) Type{std::move(*const_cast<Type *>(instance))};
- }
- }
- return (static_cast<basic_any *>(to)->instance = std::exchange(const_cast<basic_any &>(from).instance, nullptr));
- case operation::DTOR:
- if(from.mode == policy::OWNER) {
- if constexpr(in_situ<Type>) {
- instance->~Type();
- } else if constexpr(std::is_array_v<Type>) {
- delete[] instance;
- } else {
- delete instance;
- }
- }
- break;
- case operation::COMP:
- return compare<Type>(instance, (*static_cast<const basic_any **>(to))->data()) ? to : nullptr;
- case operation::ADDR:
- if(from.mode == policy::CREF) {
- return nullptr;
- }
- [[fallthrough]];
- case operation::CADDR:
- return instance;
- case operation::TYPE:
- *static_cast<type_info *>(to) = type_id<Type>();
- break;
- }
- }
- return nullptr;
- }
- template<typename Type, typename... Args>
- void initialize([[maybe_unused]] Args &&... args) {
- if constexpr(!std::is_void_v<Type>) {
- if constexpr(std::is_lvalue_reference_v<Type>) {
- static_assert(sizeof...(Args) == 1u && (std::is_lvalue_reference_v<Args> && ...), "Invalid arguments");
- 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()},
- 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. */
- basic_any() ENTT_NOEXCEPT
- : instance{},
- vtable{&basic_vtable<void>},
- 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)
- : instance{},
- vtable{&basic_vtable<std::remove_const_t<std::remove_reference_t<Type>>>},
- mode{type_to_policy<Type>()}
- {
- initialize<Type>(std::forward<Args>(args)...);
- }
- /**
- * @brief Constructs a wrapper that holds an unmanaged object.
- * @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>
- basic_any(std::reference_wrapper<Type> value) ENTT_NOEXCEPT
- : basic_any{}
- {
- // invokes deprecated assignment operator (and avoids issues with vs2017)
- *this = value;
- }
- /**
- * @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)
- : instance{},
- vtable{&basic_vtable<std::decay_t<Type>>},
- mode{policy::OWNER}
- {
- 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)
- : instance{},
- vtable{&basic_vtable<void>},
- mode{policy::OWNER}
- {
- other.vtable(operation::COPY, other, this);
- }
- /**
- * @brief Move constructor.
- * @param other The instance to move from.
- */
- basic_any(basic_any &&other) ENTT_NOEXCEPT
- : instance{},
- vtable{other.vtable},
- mode{other.mode}
- {
- vtable(operation::MOVE, other, this);
- }
- /*! @brief Frees the internal storage, whatever it means. */
- ~basic_any() {
- vtable(operation::DTOR, *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();
- 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 {
- std::exchange(vtable, other.vtable)(operation::DTOR, *this, nullptr);
- other.vtable(operation::MOVE, other, this);
- 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>
- [[deprecated("Use std::in_place_type<T &>, entt::make_any<T &>, emplace<Type &> or forward_as_any instead")]]
- basic_any & operator=(std::reference_wrapper<Type> value) ENTT_NOEXCEPT {
- emplace<Type &>(value.get());
- 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 type of the contained object.
- * @return The type of the contained object, if any.
- */
- [[nodiscard]] type_info type() const ENTT_NOEXCEPT {
- type_info info{};
- vtable(operation::TYPE, *this, &info);
- 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(operation::CADDR, *this, nullptr);
- }
- /*! @copydoc data */
- [[nodiscard]] void * data() ENTT_NOEXCEPT {
- return const_cast<void *>(vtable(operation::ADDR, *this, 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) {
- std::exchange(vtable, &basic_vtable<std::remove_const_t<std::remove_reference_t<Type>>>)(operation::DTOR, *this, nullptr);
- mode = type_to_policy<Type>();
- initialize<Type>(std::forward<Args>(args)...);
- }
- /*! @brief Destroys contained object */
- void reset() {
- std::exchange(vtable, &basic_vtable<void>)(operation::DTOR, *this, 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(operation::CADDR, *this, nullptr) == 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 {
- const basic_any *trampoline = &other;
- return type() == other.type() && (vtable(operation::COMP, *this, &trampoline) || !other.data());
- }
- /**
- * @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; };
- 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 {
- // 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>(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 {
- return (data->type() == type_id<Type>() ? static_cast<const Type *>(data->data()) : nullptr);
- }
- /*! @copydoc any_cast */
- template<typename Type, std::size_t Len, std::size_t Align>
- Type * any_cast(basic_any<Len, Align> *data) ENTT_NOEXCEPT {
- // last attempt to make wrappers for const references return their values
- return (data->type() == type_id<Type>() ? static_cast<Type *>(static_cast<constness_as_t<basic_any<Len, Align>, Type> *>(data)->data()) : nullptr);
- }
- /**
- * @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)};
- }
- }
- #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 "../config/config.h"
- // #include "../core/attribute.h"
- // #include "hashed_string.hpp"
- // #include "fwd.hpp"
- namespace entt {
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- namespace internal {
- struct ENTT_API type_seq 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;
- }
- }
- /**
- * 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_seq 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_seq::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_seq<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. */
- class type_info final {
- template<typename>
- friend type_info type_id() ENTT_NOEXCEPT;
- type_info(id_type seq_v, id_type hash_v, std::string_view name_v) ENTT_NOEXCEPT
- : seq_value{seq_v},
- hash_value{hash_v},
- name_value{name_v}
- {}
- public:
- /*! @brief Default constructor. */
- type_info() ENTT_NOEXCEPT
- : type_info({}, {}, {})
- {}
- /*! @brief Default copy constructor. */
- type_info(const type_info &) ENTT_NOEXCEPT = default;
- /*! @brief Default move constructor. */
- type_info(type_info &&) ENTT_NOEXCEPT = default;
- /**
- * @brief Default copy assignment operator.
- * @return This type info object.
- */
- type_info & operator=(const type_info &) ENTT_NOEXCEPT = default;
- /**
- * @brief Default move assignment operator.
- * @return This type info object.
- */
- type_info & operator=(type_info &&) ENTT_NOEXCEPT = default;
- /**
- * @brief Checks if a type info object is properly initialized.
- * @return True if the object is properly initialized, false otherwise.
- */
- [[nodiscard]] explicit operator bool() const ENTT_NOEXCEPT {
- return name_value.data() != nullptr;
- }
- /**
- * @brief Type sequential identifier.
- * @return Type sequential identifier.
- */
- [[nodiscard]] id_type seq() const ENTT_NOEXCEPT {
- return seq_value;
- }
- /**
- * @brief Type hash.
- * @return Type hash.
- */
- [[nodiscard]] id_type hash() const ENTT_NOEXCEPT {
- return hash_value;
- }
- /**
- * @brief Type name.
- * @return Type name.
- */
- [[nodiscard]] std::string_view name() const ENTT_NOEXCEPT {
- return name_value;
- }
- /**
- * @brief Compares the contents of two type info objects.
- * @param other Object with which to compare.
- * @return False if the two contents differ, true otherwise.
- */
- [[nodiscard]] bool operator==(const type_info &other) const ENTT_NOEXCEPT {
- return hash_value == other.hash_value;
- }
- private:
- id_type seq_value;
- id_type hash_value;
- std::string_view name_value;
- };
- /**
- * @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 contents differ, false otherwise.
- */
- [[nodiscard]] inline bool operator!=(const type_info &lhs, const type_info &rhs) ENTT_NOEXCEPT {
- return !(lhs == rhs);
- }
- /**
- * @brief Returns the type info object for a given type.
- * @tparam Type Type for which to generate a type info object.
- * @return The type info object for the given type.
- */
- template<typename Type>
- [[nodiscard]] type_info type_id() ENTT_NOEXCEPT {
- return type_info{
- type_seq<std::remove_cv_t<std::remove_reference_t<Type>>>::value(),
- type_hash<std::remove_cv_t<std::remove_reference_t<Type>>>::value(),
- type_name<std::remove_cv_t<std::remove_reference_t<Type>>>::value()
- };
- }
- }
- #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<class 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_t = 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_v = 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::disjunction_v<std::is_same<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<class 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;
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- namespace internal {
- template<typename>
- [[nodiscard]] constexpr bool is_equality_comparable(...) { return false; }
- template<typename Type>
- [[nodiscard]] constexpr auto is_equality_comparable(choice_t<0>)
- -> decltype(std::declval<Type>() == std::declval<Type>()) { return true; }
- template<typename Type>
- [[nodiscard]] constexpr auto is_equality_comparable(choice_t<1>)
- -> decltype(std::declval<typename Type::value_type>(), std::declval<Type>() == std::declval<Type>()) {
- if constexpr(std::is_same_v<typename Type::value_type, Type>) {
- return is_equality_comparable<Type>(choice<0>);
- } else {
- return is_equality_comparable<typename Type::value_type>(choice<2>);
- }
- }
- template<typename Type>
- [[nodiscard]] constexpr auto is_equality_comparable(choice_t<2>)
- -> decltype(std::declval<typename Type::mapped_type>(), std::declval<Type>() == std::declval<Type>()) {
- return is_equality_comparable<typename Type::key_type>(choice<2>) && is_equality_comparable<typename Type::mapped_type>(choice<2>);
- }
- }
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /**
- * @brief Provides the member constant `value` to true if a given type is
- * equality comparable, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_equality_comparable: std::bool_constant<internal::is_equality_comparable<Type>(choice<2>)> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<class Type>
- inline constexpr bool is_equality_comparable_v = is_equality_comparable<Type>::value;
- /*! @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 {};
- /*! @copydoc is_iterator */
- template<typename Type>
- struct is_iterator<Type, std::void_t<typename std::iterator_traits<Type>::iterator_category>>
- : std::true_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 of the
- * required iterator type, false otherwise.
- * @tparam Type The type to test.
- * @tparam It Required iterator type.
- */
- template<typename Type, typename It, typename = void>
- struct is_iterator_type: std::false_type {};
- /*! @copydoc is_iterator_type */
- template<typename Type, typename It>
- struct is_iterator_type<Type, It, std::enable_if_t<is_iterator_v<Type> && std::is_same_v<Type, It>>>
- : std::true_type
- {};
- /*! @copydoc is_iterator_type */
- template<typename Type, typename It>
- struct is_iterator_type<Type, It, std::enable_if_t<!std::is_same_v<Type, It>, std::void_t<typename It::iterator_type>>>
- : is_iterator_type<Type, typename It::iterator_type>
- {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- * @tparam It Required iterator type.
- */
- template<typename Type, typename It>
- inline constexpr bool is_iterator_type_v = is_iterator_type<Type, It>::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;
- }
- #endif
- // #include "fwd.hpp"
- #ifndef ENTT_POLY_FWD_HPP
- #define ENTT_POLY_FWD_HPP
- #include <type_traits>
- namespace entt {
- template<typename, std::size_t Len, 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, sizeof(double[2])>;
- }
- #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<auto Member, typename... Args>
- poly_inspector invoke(Args &&... args) const;
- /*! @copydoc invoke */
- template<auto 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...>)
- -> decltype(std::make_tuple(vtable_entry(Candidate)...));
- template<typename... Func>
- [[nodiscard]] static constexpr auto make_vtable(type_list<Func...>) {
- if constexpr(sizeof...(Func) == 0) {
- 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...)) {
- 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...>) {
- type impl{};
- (fill_vtable_entry<Type, value_list_element_v<Index, typename Concept::template impl<Type>>>(std::get<Index>(impl)), ...);
- return impl;
- }
- public:
- /*! @brief Virtual table type. */
- using type = decltype(make_vtable(Concept{}));
- /**
- * @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 const auto * instance() {
- static_assert(std::is_same_v<Type, std::decay_t<Type>>, "Type differs from its decayed form");
- static const auto vtable = fill_vtable<Type>(std::make_index_sequence<Concept::template impl<Type>::size>{});
- 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<auto Member, typename... Args>
- [[nodiscard]] decltype(auto) invoke(const poly_base &self, Args &&... args) const {
- const auto &poly = static_cast<const Poly &>(self);
- return std::get<Member>(*poly.vtable)(poly.storage, std::forward<Args>(args)...);
- }
- /*! @copydoc invoke */
- template<auto Member, typename... Args>
- [[nodiscard]] decltype(auto) invoke(poly_base &self, Args &&... args) {
- auto &poly = static_cast<Poly &>(self);
- 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<auto 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>;
- using vtable_type = typename poly_vtable<Concept, Len, Align>::type;
- public:
- /*! @brief Concept type. */
- using concept_type = typename Concept::template type<poly_base<basic_poly>>;
- /*! @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_const_t<std::remove_reference_t<Type>>>()}
- {}
- /**
- * @brief Constructs a poly from a given value.
- * @tparam Type Type of object to use to initialize the poly.
- * @param value An instance of an object to use to initialize the poly.
- */
- template<typename Type, typename = std::enable_if_t<!std::is_same_v<std::remove_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 Copy constructor.
- * @param other The instance to copy from.
- */
- basic_poly(const basic_poly &other) = default;
- /**
- * @brief Move constructor.
- * @param other The instance to move from.
- */
- basic_poly(basic_poly &&other) ENTT_NOEXCEPT
- : basic_poly{}
- {
- swap(*this, other);
- }
- /**
- * @brief Assignment operator.
- * @param other The instance to assign from.
- * @return This poly object.
- */
- basic_poly & operator=(basic_poly other) {
- swap(other, *this);
- return *this;
- }
- /**
- * @brief Returns the type of the contained object.
- * @return The type of the contained object, if any.
- */
- [[nodiscard]] 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) {
- *this = basic_poly{std::in_place_type<Type>, std::forward<Args>(args)...};
- }
- /*! @brief Destroys contained object */
- void reset() {
- *this = basic_poly{};
- }
- /**
- * @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 !(vtable == nullptr);
- }
- /**
- * @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 Swaps two poly objects.
- * @param lhs A valid poly object.
- * @param rhs A valid poly object.
- */
- friend void swap(basic_poly &lhs, basic_poly &rhs) {
- using std::swap;
- swap(lhs.storage, rhs.storage);
- swap(lhs.vtable, rhs.vtable);
- }
- /**
- * @brief Aliasing constructor.
- * @return A poly that shares a reference to an unmanaged object.
- */
- [[nodiscard]] basic_poly as_ref() ENTT_NOEXCEPT {
- basic_poly ref = std::as_const(*this).as_ref();
- ref.storage = storage.as_ref();
- 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;
- const vtable_type *vtable;
- };
- }
- #endif
- // #include "fwd.hpp"
- namespace entt {
- /**
- * @brief Basic poly storage implementation.
- * @tparam Entity A valid entity type (see entt_traits for more details).
- */
- template<typename Entity>
- struct Storage: type_list<type_info() const ENTT_NOEXCEPT> {
- /**
- * @brief Concept definition.
- * @tparam Base Opaque base class from which to inherit.
- */
- template<typename Base>
- struct type: Base {
- /**
- * @brief Returns a type info for the contained objects.
- * @return The type info for the contained objects.
- */
- type_info value_type() const ENTT_NOEXCEPT {
- return poly_call<0>(*this);
- }
- };
- /**
- * @brief Concept implementation.
- * @tparam Type Type for which to generate an implementation.
- */
- template<typename Type>
- using impl = value_list<&type_id<typename Type::value_type>>;
- };
- /**
- * @brief Defines the poly storage type associate with a given entity type.
- * @tparam Entity A valid entity type (see entt_traits for more details).
- */
- template<typename Entity, typename = void>
- struct poly_storage_traits {
- /*! @brief Poly storage type for the given entity type. */
- using storage_type = poly<Storage<Entity>>;
- };
- }
- #endif
- // #include "runtime_view.hpp"
- #ifndef ENTT_ENTITY_RUNTIME_VIEW_HPP
- #define ENTT_ENTITY_RUNTIME_VIEW_HPP
- #include <iterator>
- #include <vector>
- #include <utility>
- #include <algorithm>
- #include <type_traits>
- // #include "../config/config.h"
- // #include "entity.hpp"
- // #include "sparse_set.hpp"
- // #include "fwd.hpp"
- namespace entt {
- /**
- * @brief 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).
- */
- template<typename Entity>
- class basic_runtime_view final {
- using basic_common_type = basic_sparse_set<Entity>;
- using underlying_iterator = typename basic_common_type::iterator;
- class view_iterator final {
- [[nodiscard]] bool valid() const {
- const auto entt = *it;
- return (!stable_storage || (entt != tombstone))
- && std::all_of(pools->begin()++, pools->end(), [entt](const auto *curr) { return curr->contains(entt); })
- && std::none_of(filter->cbegin(), filter->cend(), [entt](const auto *curr) { return curr && curr->contains(entt); });
- }
- public:
- using difference_type = typename underlying_iterator::difference_type;
- using value_type = typename underlying_iterator::value_type;
- using pointer = typename underlying_iterator::pointer;
- using reference = typename underlying_iterator::reference;
- using iterator_category = std::bidirectional_iterator_tag;
- view_iterator() ENTT_NOEXCEPT = default;
- view_iterator(const std::vector<const basic_common_type *> &cpools, const std::vector<const basic_common_type *> &ignore, underlying_iterator curr) ENTT_NOEXCEPT
- : pools{&cpools},
- filter{&ignore},
- it{curr},
- stable_storage{std::any_of(pools->cbegin(), pools->cend(), [](const basic_common_type *cpool) { return (cpool->policy() == deletion_policy::in_place); })}
- {
- if(it != (*pools)[0]->end() && !valid()) {
- ++(*this);
- }
- }
- view_iterator & operator++() {
- while(++it != (*pools)[0]->end() && !valid());
- return *this;
- }
- view_iterator operator++(int) {
- view_iterator orig = *this;
- return ++(*this), orig;
- }
- view_iterator & operator--() ENTT_NOEXCEPT {
- while(--it != (*pools)[0]->begin() && !valid());
- return *this;
- }
- view_iterator operator--(int) ENTT_NOEXCEPT {
- view_iterator orig = *this;
- return operator--(), orig;
- }
- [[nodiscard]] bool operator==(const view_iterator &other) const ENTT_NOEXCEPT {
- return other.it == it;
- }
- [[nodiscard]] bool operator!=(const view_iterator &other) const ENTT_NOEXCEPT {
- return !(*this == other);
- }
- [[nodiscard]] pointer operator->() const {
- return it.operator->();
- }
- [[nodiscard]] reference operator*() const {
- return *operator->();
- }
- private:
- const std::vector<const basic_common_type *> *pools;
- const std::vector<const basic_common_type *> *filter;
- underlying_iterator it;
- bool stable_storage;
- };
- [[nodiscard]] bool valid() const {
- return !pools.empty() && pools.front();
- }
- public:
- /*! @brief Underlying entity identifier. */
- using entity_type = Entity;
- /*! @brief Unsigned integer type. */
- using size_type = std::size_t;
- /*! @brief Bidirectional iterator type. */
- using iterator = view_iterator;
- /*! @brief Default constructor to use to create empty, invalid views. */
- basic_runtime_view() ENTT_NOEXCEPT
- : pools{},
- filter{}
- {}
- /**
- * @brief Constructs a runtime view from a set of storage classes.
- * @param cpools The storage for the types to iterate.
- * @param epools The storage for the types used to filter the view.
- */
- basic_runtime_view(std::vector<const basic_common_type *> cpools, std::vector<const basic_common_type *> epools) ENTT_NOEXCEPT
- : pools{std::move(cpools)},
- filter{std::move(epools)}
- {
- // brings the best candidate (if any) on front of the vector
- std::rotate(pools.begin(), std::min_element(pools.begin(), pools.end(), [](const auto *lhs, const auto *rhs) {
- return (!lhs && rhs) || (lhs && rhs && lhs->size() < rhs->size());
- }), pools.end());
- }
- /**
- * @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 valid() ? pools.front()->size() : size_type{};
- }
- /**
- * @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 valid() ? iterator{pools, filter, pools[0]->begin()} : iterator{};
- }
- /**
- * @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 valid() ? iterator{pools, filter, pools[0]->end()} : iterator{};
- }
- /**
- * @brief Checks if a view contains an entity.
- * @param entt A valid entity identifier.
- * @return True if the view contains the given entity, false otherwise.
- */
- [[nodiscard]] bool contains(const entity_type entt) const {
- return valid() && 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 basic_common_type *> pools;
- std::vector<const basic_common_type *> filter;
- };
- }
- #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 <iterator>
- #include <array>
- #include <tuple>
- #include <utility>
- #include <algorithm>
- #include <type_traits>
- // #include "../config/config.h"
- // #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 Policy, typename It, std::size_t AllOf, std::size_t NoneOf>
- class view_iterator final {
- using basic_common_type = basic_sparse_set<typename std::iterator_traits<It>::value_type>;
- [[nodiscard]] bool valid() const {
- const auto entt = *it;
- return Policy::accept(entt)
- && std::apply([entt](const auto *... curr) { return (curr->contains(entt) && ...); }, pools)
- && std::apply([entt](const auto *... curr) { return (!curr->contains(entt) && ...); }, filter);
- }
- public:
- using iterator_type = It;
- using difference_type = typename std::iterator_traits<It>::difference_type;
- using value_type = typename std::iterator_traits<It>::value_type;
- using pointer = typename std::iterator_traits<It>::pointer;
- using reference = typename std::iterator_traits<It>::reference;
- using iterator_category = std::bidirectional_iterator_tag;
- view_iterator() ENTT_NOEXCEPT
- : first{},
- last{},
- it{},
- pools{},
- filter{}
- {}
- view_iterator(It from, It to, It curr, std::array<const basic_common_type *, AllOf> all_of, std::array<const basic_common_type *, NoneOf> none_of) ENTT_NOEXCEPT
- : first{from},
- last{to},
- it{curr},
- 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;
- }
- view_iterator & operator--() ENTT_NOEXCEPT {
- while(--it != first && !valid());
- return *this;
- }
- view_iterator operator--(int) ENTT_NOEXCEPT {
- view_iterator orig = *this;
- return operator--(), orig;
- }
- [[nodiscard]] bool operator==(const view_iterator &other) const ENTT_NOEXCEPT {
- return other.it == it;
- }
- [[nodiscard]] bool operator!=(const view_iterator &other) const ENTT_NOEXCEPT {
- return !(*this == other);
- }
- [[nodiscard]] pointer operator->() const {
- return &*it;
- }
- [[nodiscard]] reference operator*() const {
- return *operator->();
- }
- private:
- It first;
- It last;
- It it;
- std::array<const basic_common_type *, AllOf> pools;
- std::array<const basic_common_type *, NoneOf> filter;
- };
- }
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /*! @brief Stable storage policy, aimed at pointer stability. */
- struct stable_storage_policy {
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- template<typename Entity>
- [[nodiscard]] static constexpr bool accept(const Entity entity) ENTT_NOEXCEPT {
- return entity != tombstone;
- }
- /**
- * Internal details not to be documented.
- * @endcond
- */
- };
- /*! @brief Packed storage policy, aimed at faster linear iteration. */
- struct packed_storage_policy {
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- template<typename Entity>
- [[nodiscard]] static constexpr bool accept(const Entity) ENTT_NOEXCEPT {
- return true;
- }
- /**
- * 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...>
- class basic_view_impl;
- /*! @brief View implementation dispatcher. */
- template<typename...>
- struct 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.
- *
- * @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 views.
- *
- * @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 Policy Common (stricter) storage policy.
- * @tparam Entity A valid entity type (see entt_traits for more details).
- * @tparam Exclude Types of components used to filter the view.
- * @tparam Component Types of components iterated by the view.
- */
- template<typename Policy, typename Entity, typename... Exclude, typename... Component>
- class basic_view_impl<Policy, Entity, exclude_t<Exclude...>, Component...> {
- using basic_common_type = basic_sparse_set<Entity>;
- template<typename Comp>
- using storage_type = constness_as_t<typename storage_traits<Entity, std::remove_const_t<Comp>>::storage_type, Comp>;
- class iterable final {
- template<typename It>
- struct iterable_iterator final {
- using difference_type = std::ptrdiff_t;
- using value_type = decltype(std::tuple_cat(std::tuple<Entity>{}, std::declval<basic_view_impl>().get({})));
- using pointer = void;
- using reference = value_type;
- using iterator_category = std::input_iterator_tag;
- iterable_iterator(It from, const basic_view_impl *parent) ENTT_NOEXCEPT
- : it{from},
- view{parent}
- {}
- iterable_iterator & operator++() ENTT_NOEXCEPT {
- return ++it, *this;
- }
- iterable_iterator operator++(int) ENTT_NOEXCEPT {
- iterable_iterator orig = *this;
- return ++(*this), orig;
- }
- [[nodiscard]] reference operator*() const ENTT_NOEXCEPT {
- return std::tuple_cat(std::make_tuple(*it), view->get(*it));
- }
- [[nodiscard]] bool operator==(const iterable_iterator &other) const ENTT_NOEXCEPT {
- return other.it == it;
- }
- [[nodiscard]] bool operator!=(const iterable_iterator &other) const ENTT_NOEXCEPT {
- return !(*this == other);
- }
- private:
- It it;
- const basic_view_impl *view;
- };
- public:
- using iterator = iterable_iterator<internal::view_iterator<Policy, typename basic_common_type::iterator, sizeof...(Component) - 1u, sizeof...(Exclude)>>;
- using reverse_iterator = iterable_iterator<internal::view_iterator<Policy, typename basic_common_type::reverse_iterator, sizeof...(Component) - 1u, sizeof...(Exclude)>>;
- iterable(const basic_view_impl &parent)
- : view{parent}
- {}
- [[nodiscard]] iterator begin() const ENTT_NOEXCEPT {
- return { view.begin(), &view };
- }
- [[nodiscard]] iterator end() const ENTT_NOEXCEPT {
- return { view.end(), &view };
- }
- [[nodiscard]] reverse_iterator rbegin() const ENTT_NOEXCEPT {
- return { view.rbegin(), &view };
- }
- [[nodiscard]] reverse_iterator rend() const ENTT_NOEXCEPT {
- return { view.rend(), &view };
- }
- private:
- const basic_view_impl view;
- };
- [[nodiscard]] const auto * candidate() const ENTT_NOEXCEPT {
- return (std::min)({ static_cast<const basic_common_type *>(std::get<storage_type<Component> *>(pools))... }, [](const auto *lhs, const auto *rhs) {
- return lhs->size() < rhs->size();
- });
- }
- [[nodiscard]] auto pools_to_unchecked_array() const ENTT_NOEXCEPT {
- std::size_t pos{};
- std::array<const basic_common_type *, sizeof...(Component) - 1u> other{};
- (static_cast<void>(std::get<storage_type<Component> *>(pools) == view ? void() : void(other[pos++] = std::get<storage_type<Component> *>(pools))), ...);
- return other;
- }
- [[nodiscard]] auto filter_to_array() const ENTT_NOEXCEPT {
- return std::array<const basic_common_type *, sizeof...(Exclude)>{std::get<const storage_type<Exclude> *>(filter)...};
- }
- template<typename Comp, typename It>
- [[nodiscard]] auto dispatch_get([[maybe_unused]] It &it, [[maybe_unused]] const Entity entt) const {
- if constexpr(std::is_same_v<typename std::iterator_traits<It>::value_type, typename storage_type<Comp>::value_type>) {
- return std::forward_as_tuple(*it);
- } else {
- return get_as_tuple(*std::get<storage_type<Comp> *>(pools), entt);
- }
- }
- template<typename Comp, typename Func>
- void traverse(Func func) const {
- if constexpr(std::is_void_v<decltype(std::get<storage_type<Comp> *>(pools)->get({}))>) {
- for(const auto entt: static_cast<const basic_common_type &>(*std::get<storage_type<Comp> *>(pools))) {
- if(Policy::accept(entt) && ((std::is_same_v<Comp, Component> || std::get<storage_type<Component> *>(pools)->contains(entt)) && ...)
- && (!std::get<const storage_type<Exclude> *>(filter)->contains(entt) && ...))
- {
- if constexpr(is_applicable_v<Func, decltype(std::tuple_cat(std::tuple<entity_type>{}, std::declval<basic_view_impl>().get({})))>) {
- std::apply(func, std::tuple_cat(std::make_tuple(entt), get(entt)));
- } else {
- std::apply(func, get(entt));
- }
- }
- }
- } else {
- auto it = std::get<storage_type<Comp> *>(pools)->begin();
- for(const auto entt: static_cast<const basic_common_type &>(*std::get<storage_type<Comp> *>(pools))) {
- if(Policy::accept(entt) && ((std::is_same_v<Comp, Component> || std::get<storage_type<Component> *>(pools)->contains(entt)) && ...)
- && (!std::get<const storage_type<Exclude> *>(filter)->contains(entt) && ...))
- {
- if constexpr(is_applicable_v<Func, decltype(std::tuple_cat(std::tuple<entity_type>{}, std::declval<basic_view_impl>().get({})))>) {
- std::apply(func, std::tuple_cat(std::make_tuple(entt), dispatch_get<Component>(it, entt)...));
- } else {
- std::apply(func, std::tuple_cat(dispatch_get<Component>(it, entt)...));
- }
- }
- ++it;
- }
- }
- }
- public:
- /*! @brief Underlying entity identifier. */
- using entity_type = Entity;
- /*! @brief Unsigned integer type. */
- using size_type = std::size_t;
- /*! @brief Bidirectional iterator type. */
- using iterator = internal::view_iterator<Policy, typename basic_common_type::iterator, sizeof...(Component) - 1u, sizeof...(Exclude)>;
- /*! @brief Reverse iterator type. */
- using reverse_iterator = internal::view_iterator<Policy, typename basic_common_type::reverse_iterator, sizeof...(Component) - 1u, sizeof...(Exclude)>;
- /*! @brief Iterable view type. */
- using iterable_view = iterable;
- /*! @brief Default constructor to use to create empty, invalid views. */
- basic_view_impl() ENTT_NOEXCEPT
- : 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_impl(storage_type<Component> &... component, const storage_type<Exclude> &... epool) ENTT_NOEXCEPT
- : pools{&component...},
- filter{&epool...},
- view{candidate()}
- {}
- /**
- * @brief Forces the type to use to drive iterations.
- * @tparam Comp Type of component to use to drive the iteration.
- */
- template<typename Comp>
- void use() const ENTT_NOEXCEPT {
- view = std::get<storage_type<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 {
- return iterator{view->begin(), view->end(), view->begin(), pools_to_unchecked_array(), filter_to_array()};
- }
- /**
- * @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 {
- return iterator{view->begin(), view->end(), view->end(), pools_to_unchecked_array(), filter_to_array()};
- }
- /**
- * @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 {
- return reverse_iterator{view->rbegin(), view->rend(), view->rbegin(), pools_to_unchecked_array(), filter_to_array()};
- }
- /**
- * @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 {
- return reverse_iterator{view->rbegin(), view->rend(), view->rend(), pools_to_unchecked_array(), filter_to_array()};
- }
- /**
- * @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 {
- 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 {
- const auto it = rbegin();
- return it != rend() ? *it : null;
- }
- /**
- * @brief Finds an entity.
- * @param entt A valid entity 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 {
- const auto it = iterator{view->begin(), view->end(), view->find(entt), pools_to_unchecked_array(), filter_to_array()};
- return (it != end() && *it == entt) ? it : end();
- }
- /**
- * @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 entity identifier.
- * @return True if the view contains the given entity, false otherwise.
- */
- [[nodiscard]] bool contains(const entity_type entt) const {
- return (std::get<storage_type<Component> *>(pools)->contains(entt) && ...) && (!std::get<const storage_type<Exclude> *>(filter)->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 view
- * results in undefined behavior.
- *
- * @tparam Comp Types of components to get.
- * @param entt A valid entity identifier.
- * @return The components assigned to the entity.
- */
- template<typename... Comp>
- [[nodiscard]] decltype(auto) get([[maybe_unused]] const entity_type entt) const {
- ENTT_ASSERT(contains(entt), "View does not contain entity");
- if constexpr(sizeof...(Comp) == 0) {
- return std::tuple_cat(get_as_tuple(*std::get<storage_type<Component> *>(pools), entt)...);
- } else if constexpr(sizeof...(Comp) == 1) {
- return (std::get<storage_type<Comp> *>(pools)->get(entt), ...);
- } else {
- return std::tuple_cat(get_as_tuple(*std::get<storage_type<Comp> *>(pools), 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 {
- ((std::get<storage_type<Component> *>(pools) == view ? traverse<Component>(std::move(func)) : void()), ...);
- }
- /**
- * @brief Iterates entities and components and applies the given function
- * object to them.
- *
- * The pool of the suggested component is used to lead the iterations. The
- * returned entities will therefore respect the order of the pool associated
- * with that type.
- *
- * @sa each
- *
- * @tparam Comp Type of component to use to drive the iteration.
- * @tparam Func Type of the function object to invoke.
- * @param func A valid function object.
- */
- template<typename Comp, typename Func>
- void each(Func func) const {
- use<Comp>();
- traverse<Comp>(std::move(func));
- }
- /**
- * @brief Returns an iterable object to use to _visit_ the view.
- *
- * 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 view.
- */
- [[nodiscard]] iterable_view each() const ENTT_NOEXCEPT {
- return iterable_view{*this};
- }
- /**
- * @brief Returns an iterable object to use to _visit_ the view.
- *
- * The pool of the suggested component is used to lead the iterations. The
- * returned elements will therefore respect the order of the pool associated
- * with that type.
- *
- * @sa each
- *
- * @tparam Comp Type of component to use to drive the iteration.
- * @return An iterable object to use to _visit_ the view.
- */
- template<typename Comp>
- [[nodiscard]] iterable_view each() const ENTT_NOEXCEPT {
- use<Comp>();
- return iterable_view{*this};
- }
- /**
- * @brief Combines two views in a _more specific_ one (friend function).
- * @tparam Id A valid entity type (see entt_traits for more details).
- * @tparam ELhs Filter list of the first view.
- * @tparam CLhs Component list of the first view.
- * @tparam ERhs Filter list of the second view.
- * @tparam CRhs Component list of the second view.
- * @return A more specific view.
- */
- template<typename Id, typename... ELhs, typename... CLhs, typename... ERhs, typename... CRhs>
- friend auto operator|(const basic_view<Id, exclude_t<ELhs...>, CLhs...> &, const basic_view<Id, exclude_t<ERhs...>, CRhs...> &);
- private:
- const std::tuple<storage_type<Component> *...> pools;
- const std::tuple<const storage_type<Exclude> *...> filter;
- mutable const basic_common_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.
- *
- * @note
- * Views share a reference to the underlying data structure 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 views.
- *
- * @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 Component Type of component iterated by the view.
- */
- template<typename Entity, typename Component>
- class basic_view_impl<packed_storage_policy, Entity, exclude_t<>, Component> {
- using basic_common_type = basic_sparse_set<Entity>;
- using storage_type = constness_as_t<typename storage_traits<Entity, std::remove_const_t<Component>>::storage_type, Component>;
- class iterable final {
- template<typename... It>
- struct iterable_iterator final {
- using difference_type = std::ptrdiff_t;
- using value_type = decltype(std::tuple_cat(std::tuple<Entity>{}, std::declval<basic_view_impl>().get({})));
- using pointer = void;
- using reference = value_type;
- using iterator_category = std::input_iterator_tag;
- template<typename... Discard>
- iterable_iterator(It... from, Discard...) ENTT_NOEXCEPT
- : it{from...}
- {}
- iterable_iterator & operator++() ENTT_NOEXCEPT {
- return (++std::get<It>(it), ...), *this;
- }
- iterable_iterator operator++(int) ENTT_NOEXCEPT {
- iterable_iterator orig = *this;
- return ++(*this), orig;
- }
- [[nodiscard]] reference operator*() const ENTT_NOEXCEPT {
- return { *std::get<It>(it)... };
- }
- [[nodiscard]] bool operator==(const iterable_iterator &other) const ENTT_NOEXCEPT {
- return std::get<0>(other.it) == std::get<0>(it);
- }
- [[nodiscard]] bool operator!=(const iterable_iterator &other) const ENTT_NOEXCEPT {
- return !(*this == other);
- }
- private:
- std::tuple<It...> it;
- };
- public:
- using iterator = std::conditional_t<
- std::is_void_v<decltype(std::declval<storage_type>().get({}))>,
- iterable_iterator<typename basic_common_type::iterator>,
- iterable_iterator<typename basic_common_type::iterator, decltype(std::declval<storage_type>().begin())>
- >;
- using reverse_iterator = std::conditional_t<
- std::is_void_v<decltype(std::declval<storage_type>().get({}))>,
- iterable_iterator<typename basic_common_type::reverse_iterator>,
- iterable_iterator<typename basic_common_type::reverse_iterator, decltype(std::declval<storage_type>().rbegin())>
- >;
- iterable(storage_type &ref)
- : pool{&ref}
- {}
- [[nodiscard]] iterator begin() const ENTT_NOEXCEPT {
- return iterator{pool->basic_common_type::begin(), pool->begin()};
- }
- [[nodiscard]] iterator end() const ENTT_NOEXCEPT {
- return iterator{pool->basic_common_type::end(), pool->end()};
- }
- [[nodiscard]] reverse_iterator rbegin() const ENTT_NOEXCEPT {
- return reverse_iterator{pool->basic_common_type::rbegin(), pool->rbegin()};
- }
- [[nodiscard]] reverse_iterator rend() const ENTT_NOEXCEPT {
- return reverse_iterator{pool->basic_common_type::rend(), pool->rend()};
- }
- private:
- storage_type * const pool;
- };
- 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_common_type::iterator;
- /*! @brief Reversed iterator type. */
- using reverse_iterator = typename basic_common_type::reverse_iterator;
- /*! @brief Iterable view type. */
- using iterable_view = iterable;
- /*! @brief Default constructor to use to create empty, invalid views. */
- basic_view_impl() ENTT_NOEXCEPT
- : pools{},
- filter{}
- {}
- /**
- * @brief Constructs a single-type view from a storage class.
- * @param ref The storage for the type to iterate.
- */
- basic_view_impl(storage_type &ref) ENTT_NOEXCEPT
- : pools{&ref},
- filter{}
- {}
- /**
- * @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 std::get<0>(pools)->size();
- }
- /**
- * @brief Checks whether a view is empty.
- * @return True if the view is empty, false otherwise.
- */
- [[nodiscard]] bool empty() const ENTT_NOEXCEPT {
- return std::get<0>(pools)->empty();
- }
- /**
- * @brief Direct access to the raw representation offered by the storage.
- * @return A pointer to the array of components.
- */
- [[nodiscard]] auto raw() const ENTT_NOEXCEPT {
- return std::get<0>(pools)->raw();
- }
- /**
- * @brief Direct access to the list of entities.
- *
- * The returned pointer is such that range `[data(), data() + size())` is
- * always a valid range, even if the container is empty.
- *
- * @return A pointer to the array of entities.
- */
- [[nodiscard]] auto data() const ENTT_NOEXCEPT {
- return std::get<0>(pools)->data();
- }
- /**
- * @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 std::get<0>(pools)->basic_common_type::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 std::get<0>(pools)->basic_common_type::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 std::get<0>(pools)->basic_common_type::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 std::get<0>(pools)->basic_common_type::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 {
- 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 {
- const auto it = rbegin();
- return it != rend() ? *it : null;
- }
- /**
- * @brief Finds an entity.
- * @param entt A valid entity 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 {
- const auto it = std::get<0>(pools)->find(entt);
- 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 view is properly initialized.
- * @return True if the view is properly initialized, false otherwise.
- */
- [[nodiscard]] explicit operator bool() const ENTT_NOEXCEPT {
- return std::get<0>(pools) != nullptr;
- }
- /**
- * @brief Checks if a view contains an entity.
- * @param entt A valid entity identifier.
- * @return True if the view contains the given entity, false otherwise.
- */
- [[nodiscard]] bool contains(const entity_type entt) const {
- return std::get<0>(pools)->contains(entt);
- }
- /**
- * @brief Returns the component 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 view
- * results in undefined behavior.
- *
- * @tparam Comp Types of components to get.
- * @param entt A valid entity 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 get_as_tuple(*std::get<0>(pools), entt);
- } else {
- static_assert(std::is_same_v<Comp..., Component>, "Invalid component type");
- 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
- *
- * @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 {
- if constexpr(std::is_void_v<decltype(std::get<0>(pools)->get({}))>) {
- if constexpr(std::is_invocable_v<Func>) {
- for(auto pos = size(); pos; --pos) {
- func();
- }
- } else {
- for(auto entity: *this) {
- func(entity);
- }
- }
- } else {
- if constexpr(is_applicable_v<Func, decltype(*each().begin())>) {
- for(const auto pack: each()) {
- std::apply(func, pack);
- }
- } else {
- for(auto &&component: *std::get<0>(pools)) {
- func(component);
- }
- }
- }
- }
- /**
- * @brief Returns an iterable object to use to _visit_ the view.
- *
- * The iterable object returns tuples that contain the current entity and a
- * reference to its component if it's a non-empty one. The _constness_ of
- * the component 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 view.
- */
- [[nodiscard]] iterable_view each() const ENTT_NOEXCEPT {
- return iterable_view{*std::get<0>(pools)};
- }
- /**
- * @brief Combines two views in a _more specific_ one (friend function).
- * @tparam Id A valid entity type (see entt_traits for more details).
- * @tparam ELhs Filter list of the first view.
- * @tparam CLhs Component list of the first view.
- * @tparam ERhs Filter list of the second view.
- * @tparam CRhs Component list of the second view.
- * @return A more specific view.
- */
- template<typename Id, typename... ELhs, typename... CLhs, typename... ERhs, typename... CRhs>
- friend auto operator|(const basic_view<Id, exclude_t<ELhs...>, CLhs...> &, const basic_view<Id, exclude_t<ERhs...>, CRhs...> &);
- private:
- const std::tuple<storage_type *> pools;
- const std::tuple<> filter;
- };
- /**
- * @brief View implementation dispatcher.
- * @tparam Entity A valid entity type (see entt_traits for more details).
- * @tparam Exclude Types of components used to filter the view.
- * @tparam Component Types of components iterated by the view.
- */
- template<typename Entity, typename... Exclude, typename... Component>
- struct basic_view<Entity, exclude_t<Exclude...>, Component...>
- : basic_view_impl<std::conditional_t<std::disjunction_v<typename component_traits<std::remove_const_t<Component>>::in_place_delete...>, stable_storage_policy, packed_storage_policy>, Entity, exclude_t<Exclude...>, Component...>
- {
- /*! @brief Most restrictive storage policy of all component types. */
- using storage_policy = std::conditional_t<std::disjunction_v<typename component_traits<std::remove_const_t<Component>>::in_place_delete...>, stable_storage_policy, packed_storage_policy>;
- using basic_view_impl<storage_policy, Entity, exclude_t<Exclude...>, Component...>::basic_view_impl;
- };
- /**
- * @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...>, entt::exclude_t<>, constness_as_t<typename Storage::value_type, Storage>...>;
- /**
- * @brief Combines two views in a _more specific_ one.
- * @tparam Entity A valid entity type (see entt_traits for more details).
- * @tparam ELhs Filter list of the first view.
- * @tparam CLhs Component list of the first view.
- * @tparam ERhs Filter list of the second view.
- * @tparam CRhs Component list of the second view.
- * @param lhs A valid reference to the first view.
- * @param rhs A valid reference to the second view.
- * @return A more specific view.
- */
- template<typename Entity, typename... ELhs, typename... CLhs, typename... ERhs, typename... CRhs>
- [[nodiscard]] auto operator|(const basic_view<Entity, exclude_t<ELhs...>, CLhs...> &lhs, const basic_view<Entity, exclude_t<ERhs...>, CRhs...> &rhs) {
- using view_type = basic_view<Entity, exclude_t<ELhs..., ERhs...>, CLhs..., CRhs...>;
- return std::apply([](auto *... storage) { return view_type{*storage...}; }, std::tuple_cat(lhs.pools, rhs.pools, lhs.filter, rhs.filter));
- }
- }
- #endif
- namespace entt {
- /**
- * @brief Fast and reliable entity-component system.
- *
- * The registry is the core class of the entity-component framework.<br/>
- * It stores entities and arranges pools of components on a per request basis.
- * By means of a registry, users can manage entities and components, then create
- * views or groups to iterate them.
- *
- * @tparam Entity A valid entity type (see entt_traits for more details).
- */
- template<typename Entity>
- class basic_registry {
- using traits_type = entt_traits<Entity>;
- using poly_storage_type = typename poly_storage_traits<Entity>::storage_type;
- using basic_common_type = basic_sparse_set<Entity>;
- template<typename Component>
- using storage_type = constness_as_t<typename storage_traits<Entity, std::remove_const_t<Component>>::storage_type, Component>;
- struct pool_data {
- poly_storage_type poly;
- std::unique_ptr<basic_common_type> pool{};
- };
- template<typename...>
- struct group_handler;
- template<typename... Exclude, typename... Get, typename... Owned>
- struct group_handler<exclude_t<Exclude...>, get_t<Get...>, Owned...> {
- static_assert(!std::disjunction_v<typename component_traits<Owned>::in_place_delete...>, "Groups do not support in-place delete");
- static_assert(std::conjunction_v<std::is_same<Owned, std::remove_const_t<Owned>>..., std::is_same<Get, std::remove_const_t<Get>>..., std::is_same<Exclude, std::remove_const_t<Exclude>>...>, "One or more component types are invalid");
- 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::make_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(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::make_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(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]] storage_type<Component> * assure() const {
- static_assert(std::is_same_v<Component, std::decay_t<Component>>, "Non-decayed types not allowed");
- const auto index = type_seq<Component>::value();
- if(!(index < pools.size())) {
- pools.resize(size_type(index)+1u);
- }
- if(auto &&pdata = pools[index]; !pdata.pool) {
- pdata.pool.reset(new storage_type<Component>());
- pdata.poly.template emplace<storage_type<Component> &>(*static_cast<storage_type<Component> *>(pdata.pool.get()));
- }
- return static_cast<storage_type<Component> *>(pools[index].pool.get());
- }
- template<typename Component>
- [[nodiscard]] const storage_type<Component> * pool_if_exists() const ENTT_NOEXCEPT {
- static_assert(std::is_same_v<Component, std::decay_t<Component>>, "Non-decayed types not allowed");
- const auto index = type_seq<Component>::value();
- return (!(index < pools.size()) || !pools[index].pool) ? nullptr : static_cast<const storage_type<Component> *>(pools[index].pool.get());
- }
- auto generate_identifier(const std::size_t pos) ENTT_NOEXCEPT {
- ENTT_ASSERT(pos < traits_type::to_integral(null), "No entities available");
- return traits_type::construct(static_cast<typename traits_type::entity_type>(pos), {});
- }
- auto recycle_identifier() ENTT_NOEXCEPT {
- ENTT_ASSERT(free_list != null, "No entities available");
- const auto curr = traits_type::to_entity(free_list);
- free_list = (tombstone | entities[curr]);
- return (entities[curr] = traits_type::construct(curr, traits_type::to_version(entities[curr])));
- }
- auto release_entity(const Entity entity, const typename traits_type::version_type version) {
- const typename traits_type::version_type vers = version + (version == traits_type::to_version(tombstone));
- entities[traits_type::to_entity(entity)] = traits_type::construct(traits_type::to_entity(free_list), vers);
- free_list = (tombstone | entity);
- return vers;
- }
- public:
- /*! @brief Underlying entity identifier. */
- using entity_type = Entity;
- /*! @brief Underlying version type. */
- using version_type = typename traits_type::version_type;
- /*! @brief Unsigned integer type. */
- using size_type = std::size_t;
- /*! @brief Poly storage type. */
- using poly_storage = typename poly_storage_traits<Entity>::storage_type;
- /**
- * @brief Returns the entity identifier without the version.
- * @param entity An entity identifier, either valid or not.
- * @return The entity identifier without the version.
- */
- [[nodiscard]] static entity_type entity(const entity_type entity) ENTT_NOEXCEPT {
- return traits_type::construct(traits_type::to_entity(entity), {});
- }
- /**
- * @brief Returns the version stored along with an entity identifier.
- * @param entity An entity identifier, either valid or not.
- * @return The version stored along with the given entity identifier.
- */
- [[nodiscard]] static version_type version(const entity_type entity) ENTT_NOEXCEPT {
- return traits_type::to_version(entity);
- }
- /*! @brief Default constructor. */
- basic_registry() = default;
- /*! @brief Default move constructor. */
- basic_registry(basic_registry &&) = default;
- /*! @brief Default move assignment operator. @return This registry. */
- basic_registry & operator=(basic_registry &&) = default;
- /**
- * @brief Prepares a pool for the given type if required.
- * @tparam Component Type of component for which to prepare a pool.
- */
- template<typename Component>
- void prepare() {
- // suppress the warning due to the [[nodiscard]] attribute
- static_cast<void>(assure<Component>());
- }
- /**
- * @brief Returns a poly storage for a given type.
- * @param info The type for which to return a poly storage.
- * @return A valid poly storage if a pool for the given type exists, an
- * empty and thus invalid element otherwise.
- */
- poly_storage & storage(const type_info info) {
- ENTT_ASSERT(info.seq() < pools.size() && pools[info.seq()].poly, "Storage not available");
- return pools[info.seq()].poly;
- }
- /*! @copydoc storage */
- const poly_storage & storage(const type_info info) const {
- ENTT_ASSERT(info.seq() < pools.size() && pools[info.seq()].poly, "Storage not available");
- return pools[info.seq()].poly;
- }
- /**
- * @brief Returns the number of existing components of the given type.
- * @tparam Component Type of component of which to return the size.
- * @return Number of existing components of the given type.
- */
- template<typename Component>
- [[nodiscard]] size_type size() const {
- const auto *cpool = pool_if_exists<Component>();
- return cpool ? cpool->size() : size_type{};
- }
- /**
- * @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[traits_type::to_entity(curr)];
- }
- return sz;
- }
- /**
- * @brief Increases the capacity of the registry or of the pools for the
- * given components.
- *
- * If no components are specified, the capacity of the registry is
- * increased, that is the number of entities it contains. Otherwise the
- * capacity of the pools for the given components is increased.<br/>
- * In both cases, if the new capacity is greater than the current capacity,
- * new storage is allocated, otherwise the method does nothing.
- *
- * @tparam Component Types of components for which to reserve storage.
- * @param cap Desired capacity.
- */
- template<typename... Component>
- void reserve(const size_type cap) {
- if constexpr(sizeof...(Component) == 0) {
- entities.reserve(cap);
- } else {
- (assure<Component>()->reserve(cap), ...);
- }
- }
- /**
- * @brief Reserves enough space to store `count` pools.
- * @param count Number of pools to reserve space for.
- */
- [[deprecated("No longer supported")]]
- void reserve_pools(const size_t count) {
- pools.reserve(count);
- }
- /**
- * @brief Returns the capacity of the pool for the given component.
- * @tparam Component Type of component in which one is interested.
- * @return Capacity of the pool of the given component.
- */
- template<typename Component>
- [[nodiscard]] size_type capacity() const {
- const auto *cpool = pool_if_exists<Component>();
- return cpool ? cpool->capacity() : size_type{};
- }
- /**
- * @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 Requests the removal of unused capacity for the given components.
- * @tparam Component Types of components for which to reclaim unused
- * capacity.
- */
- template<typename... Component>
- void shrink_to_fit() {
- (assure<Component>()->shrink_to_fit(), ...);
- }
- /**
- * @brief Checks whether the registry or the pools of the given components
- * are empty.
- *
- * A registry is considered empty when it doesn't contain entities that are
- * still in use.
- *
- * @tparam Component Types of components in which one is interested.
- * @return True if the registry or the pools of the given components are
- * empty, false otherwise.
- */
- template<typename... Component>
- [[nodiscard]] bool empty() const {
- if constexpr(sizeof...(Component) == 0) {
- return !alive();
- } else {
- return [](const auto *... cpool) { return ((!cpool || cpool->empty()) && ...); }(pool_if_exists<Component>()...);
- }
- }
- /**
- * @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 container 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;
- }
- /*! @copydoc released */
- [[deprecated("Use ::released instead")]]
- [[nodiscard]] entity_type destroyed() const ENTT_NOEXCEPT {
- return released();
- }
- /**
- * @brief Checks if an entity identifier refers to a valid entity.
- * @param entity An entity 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(traits_type::to_entity(entity));
- return (pos < entities.size() && entities[pos] == entity);
- }
- /**
- * @brief Returns the actual version for an entity identifier.
- *
- * @warning
- * Attempting to use an entity that doesn't belong to the registry results
- * in undefined behavior. An entity belongs to the registry even if it has
- * been previously destroyed and/or recycled.
- *
- * @param entity A valid entity identifier.
- * @return Actual version for the given entity identifier.
- */
- [[nodiscard]] version_type current(const entity_type entity) const {
- const auto pos = size_type(traits_type::to_entity(entity));
- ENTT_ASSERT(pos < entities.size(), "Entity does not exist");
- return version(entities[pos]);
- }
- /**
- * @brief Creates a new entity and returns it.
- *
- * There are two kinds of possible entity identifiers:
- *
- * * Newly created ones in case no entities have been previously destroyed.
- * * Recycled ones with updated versions.
- *
- * @return A valid entity identifier.
- */
- [[nodiscard]] entity_type create() {
- return (free_list == null) ? entities.emplace_back(generate_identifier(entities.size())) : recycle_identifier();
- }
- /**
- * @brief Creates a new entity and returns it.
- *
- * @sa create
- *
- * If the requested entity isn't in use, the suggested identifier is created
- * and returned. Otherwise, a new identifier is generated.
- *
- * @param hint Required entity identifier.
- * @return A valid entity 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 = traits_type::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 = traits_type::to_entity(entities[req]); req == curr) {
- return create();
- } else {
- auto *it = &free_list;
- for(; traits_type::to_entity(*it) != req; it = &entities[traits_type::to_entity(*it)]);
- *it = traits_type::construct(curr, traits_type::to_version(*it));
- return (entities[req] = hint);
- }
- }
- /**
- * @brief Assigns each element in a range an entity.
- *
- * @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 entities 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 entity 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 entity identifier.
- * @return The version of the recycled entity.
- */
- version_type release(const entity_type entity) {
- return release(entity, version(entity) + 1u);
- }
- /**
- * @brief Releases an entity 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 entity 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 entity 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, version(*first) + 1u);
- }
- }
- /**
- * @brief Destroys an entity and releases its identifier.
- *
- * The version is updated and the identifier can be recycled at any time.
- *
- * @warning
- * Adding or removing components to an entity that is being destroyed can
- * result in undefined behavior.
- *
- * @warning
- * Attempting to use an invalid entity results in undefined behavior.
- *
- * @param entity A valid entity identifier.
- * @return The version of the recycled entity.
- */
- version_type destroy(const entity_type entity) {
- return destroy(entity, 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 entity 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(auto &&pdata: pools) {
- pdata.pool && pdata.pool->remove(entity, this);
- }
- 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) {
- if constexpr(is_iterator_type_v<typename basic_common_type::iterator, It>) {
- for(; first != last; ++first) {
- destroy(*first, version(*first) + 1u);
- }
- } else {
- for(auto &&pdata: pools) {
- pdata.pool && pdata.pool->remove(first, last, this);
- }
- release(first, last);
- }
- }
- /**
- * @brief Assigns the given component to an entity.
- *
- * A new instance of the given component is created and initialized with the
- * arguments provided (the component must have a proper constructor or be of
- * aggregate type). Then the component is assigned to the given entity.
- *
- * @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 entity 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(*this, 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(*this, 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<std::decay_t<typename std::iterator_traits<CIt>::value_type>, Component>>>
- void insert(EIt first, EIt last, CIt from) {
- static_assert(std::is_constructible_v<Component, typename std::iterator_traits<CIt>::value_type>, "Invalid value type");
- ENTT_ASSERT(std::all_of(first, last, [this](const auto entity) { return valid(entity); }), "Invalid entity");
- assure<Component>()->insert(*this, first, last, from);
- }
- /**
- * @brief Assigns or replaces the given component for an entity.
- *
- * Equivalent to the following snippet (pseudocode):
- *
- * @code{.cpp}
- * auto &component = registry.all_of<Component>(entity) ? registry.replace<Component>(entity, args...) : registry.emplace<Component>(entity, args...);
- * @endcode
- *
- * Prefer this function anyway because it has slightly better performance.
- *
- * @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 entity 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(*this, entity, [&args...](auto &... curr) { ((curr = Component{std::forward<Args>(args)...}), ...); })
- : cpool->emplace(*this, entity, std::forward<Args>(args)...);
- }
- /**
- * @brief Patches the given component for an entity.
- *
- * The signature of the functions 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 entity 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(*this, entity, std::forward<Func>(func)...);
- }
- /**
- * @brief Replaces the given component for an entity.
- *
- * A new instance of the given component is created and initialized with the
- * arguments provided (the component must have a proper constructor or be of
- * aggregate type). Then the component is assigned to the given entity.
- *
- * @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 entity 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) {
- return assure<Component>()->patch(*this, 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 Types of components to remove.
- * @param entity A valid entity identifier.
- * @return The number of components actually removed.
- */
- template<typename... Component>
- size_type remove(const entity_type entity) {
- ENTT_ASSERT(valid(entity), "Invalid entity");
- static_assert(sizeof...(Component) > 0, "Provide one or more component types");
- return (assure<Component>()->remove(entity, this) + ... + size_type{});
- }
- /**
- * @brief Removes the given components from all the entities in a range.
- *
- * @sa remove
- *
- * @tparam Component 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 It>
- size_type remove(It first, It last) {
- static_assert(sizeof...(Component) > 0, "Provide one or more component types");
- const auto cpools = std::make_tuple(assure<Component>()...);
- size_type count{};
- for(; first != last; ++first) {
- const auto entity = *first;
- ENTT_ASSERT(valid(entity), "Invalid entity");
- count += (std::get<storage_type<Component> *>(cpools)->remove(entity, this) + ...);
- }
- 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.
- * @param entity A valid entity identifier.
- */
- template<typename... Component>
- void erase(const entity_type entity) {
- ENTT_ASSERT(valid(entity), "Invalid entity");
- static_assert(sizeof...(Component) > 0, "Provide one or more component types");
- (assure<Component>()->erase(entity, this), ...);
- }
- /**
- * @brief Erases the given components from all the entities in a range.
- *
- * @sa erase
- *
- * @tparam Component 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 It>
- void erase(It first, It last) {
- static_assert(sizeof...(Component) > 0, "Provide one or more component types");
- const auto cpools = std::make_tuple(assure<Component>()...);
- for(; first != last; ++first) {
- const auto entity = *first;
- ENTT_ASSERT(valid(entity), "Invalid entity");
- (std::get<storage_type<Component> *>(cpools)->erase(entity, this), ...);
- }
- }
- /**
- * @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 &&pdata: pools) {
- pdata.pool && (pdata.pool->compact(), true);
- }
- } else {
- (assure<Component>()->compact(), ...);
- }
- }
- /*! @copydoc remove */
- template<typename... Component>
- [[deprecated("Use ::remove instead")]]
- size_type remove_if_exists(const entity_type entity) {
- return remove<Component...>(entity);
- }
- /**
- * @brief Removes all the components from an entity and makes it orphaned.
- *
- * @warning
- * In case there are listeners that observe the destruction of components
- * and assign other components to the entity in their bodies, the result of
- * invoking this function may not be as expected. In the worst case, it
- * could lead to undefined behavior.
- *
- * @warning
- * Attempting to use an invalid entity results in undefined behavior.
- *
- * @param entity A valid entity identifier.
- */
- [[deprecated("Use ::destroy(entity)/::create(entity) instead")]]
- void remove_all(const entity_type entity) {
- ENTT_ASSERT(valid(entity), "Invalid entity");
- for(auto &&pdata: pools) {
- pdata.pool && pdata.pool->remove(entity, this);
- }
- }
- /**
- * @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 entity 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 [entity](const auto *... cpool) { return ((cpool && cpool->contains(entity)) && ...); }(pool_if_exists<Component>()...);
- }
- /**
- * @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 entity 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 [entity](const auto *... cpool) { return !((!cpool || !cpool->contains(entity)) && ...); }(pool_if_exists<Component>()...);
- }
- /**
- * @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 entity 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");
- if constexpr(sizeof...(Component) == 1) {
- const auto *cpool = pool_if_exists<std::remove_const_t<Component>...>();
- ENTT_ASSERT(cpool, "Storage not available");
- return cpool->get(entity);
- } else {
- return std::forward_as_tuple(get<Component>(entity)...);
- }
- }
- /*! @copydoc get */
- template<typename... Component>
- [[nodiscard]] decltype(auto) get([[maybe_unused]] const entity_type entity) {
- ENTT_ASSERT(valid(entity), "Invalid entity");
- if constexpr(sizeof...(Component) == 1) {
- return (const_cast<Component &>(assure<std::remove_const_t<Component>>()->get(entity)), ...);
- } else {
- return std::forward_as_tuple(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.<br/>
- * Equivalent to the following snippet (pseudocode):
- *
- * @code{.cpp}
- * auto &component = registry.all_of<Component>(entity) ? registry.get<Component>(entity) : registry.emplace<Component>(entity, args...);
- * @endcode
- *
- * Prefer this function anyway because it has slightly better performance.
- *
- * @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 entity 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(*this, 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 entity 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 = pool_if_exists<std::remove_const_t<Component>...>();
- return (cpool && cpool->contains(entity)) ? &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) {
- ENTT_ASSERT(valid(entity), "Invalid 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 &&pdata: pools) {
- pdata.pool && (pdata.pool->clear(this), true);
- }
- each([this](const auto entity) { release_entity(entity, version(entity) + 1u); });
- } else {
- (assure<Component>()->clear(this), ...);
- }
- }
- /**
- * @brief Iterates all the entities that are still in use.
- *
- * The function object is invoked for each entity that is still in use.<br/>
- * The signature of the function should be equivalent to the following:
- *
- * @code{.cpp}
- * void(const Entity);
- * @endcode
- *
- * This function is fairly slow and should not be used frequently. However,
- * it's useful for iterating all the entities still in use, regardless of
- * their components.
- *
- * @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]; traits_type::to_entity(entity) == (pos - 1)) {
- func(entity);
- }
- }
- }
- }
- /**
- * @brief Checks if an entity has components assigned.
- * @param entity A valid entity 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 &&pdata) { return pdata.pool && pdata.pool->contains(entity); });
- }
- /**
- * @brief Iterates orphans and applies them the given function object.
- *
- * The function object is invoked for each entity that is still in use and
- * has no components assigned.<br/>
- * The signature of the function should be equivalent to the following:
- *
- * @code{.cpp}
- * void(const Entity);
- * @endcode
- *
- * This function can be very slow and should not be used frequently.
- *
- * @tparam Func Type of the function object to invoke.
- * @param func A valid function object.
- */
- template<typename Func>
- void orphans(Func func) const {
- each([this, &func](const auto entity) {
- if(orphan(entity)) {
- func(entity);
- }
- });
- }
- /**
- * @brief Returns a sink object for the given component.
- *
- * The sink returned by this function can be used 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** the component has been assigned 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.
- *
- * The sink returned by this function can be used 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** the component has been updated.
- *
- * @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.
- *
- * The sink returned by this function can be used 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** the component has been removed 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.
- *
- * This kind of objects are created on the fly and share with the registry
- * its internal data structures.<br/>
- * Feel free to discard a view after the use. Creating and destroying a view
- * is an incredibly cheap operation because they do not require any type of
- * initialization.<br/>
- * As a rule of thumb, storing a view should never be an option.
- *
- * Views do their best to iterate the smallest set of candidate entities.
- * In particular:
- *
- * * Single component views are incredibly fast and iterate a packed array
- * of entities, all of which has the given component.
- * * Multi component views look at the number of entities available for each
- * component and pick up a reference to the smallest set of candidates to
- * test for the given components.
- *
- * Views in no way affect the functionalities of the registry nor those of
- * the underlying pools.
- *
- * @note
- * Multi component views are pretty fast. However their performance tend to
- * degenerate when the number of components to iterate grows up and the most
- * of the entities have all the given components.<br/>
- * To get a performance boost, consider using a group instead.
- *
- * @tparam Component Type 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... Exclude>
- [[nodiscard]] basic_view<Entity, exclude_t<Exclude...>, std::add_const_t<Component>...> view(exclude_t<Exclude...> = {}) const {
- static_assert(sizeof...(Component) > 0, "Exclusion-only views are not supported");
- return { *assure<std::remove_const_t<Component>>()..., *assure<Exclude>()... };
- }
- /*! @copydoc view */
- template<typename... Component, typename... Exclude>
- [[nodiscard]] basic_view<Entity, exclude_t<Exclude...>, Component...> view(exclude_t<Exclude...> = {}) {
- static_assert(sizeof...(Component) > 0, "Exclusion-only views are not supported");
- return { *assure<std::remove_const_t<Component>>()..., *assure<Exclude>()... };
- }
- /**
- * @brief Returns a runtime view for the given components.
- *
- * This kind of objects are created on the fly and share with the registry
- * its internal data structures.<br/>
- * Users should throw away the view after use. Fortunately, creating and
- * destroying a runtime view is an incredibly cheap operation because they
- * do not require any type of initialization.<br/>
- * As a rule of thumb, storing a view should never be an option.
- *
- * Runtime views are to be used when users want to construct a view from
- * some external inputs and don't know at compile-time what are the required
- * components.
- *
- * @tparam ItComp Type of input iterator for the components to use to
- * construct the view.
- * @tparam ItExcl Type of input iterator for the components to use to filter
- * the view.
- * @param first An iterator to the first element of the range of components
- * to use to construct the view.
- * @param last An iterator past the last element of the range of components
- * to use to construct the view.
- * @param from An iterator to the first element of the range of components
- * to use to filter the view.
- * @param to An iterator past the last element of the range of components to
- * use to filter the view.
- * @return A newly created runtime view.
- */
- template<typename ItComp, typename ItExcl = id_type *>
- [[nodiscard]] basic_runtime_view<Entity> runtime_view(ItComp first, ItComp last, ItExcl from = {}, ItExcl to = {}) const {
- std::vector<const basic_common_type *> component(std::distance(first, last));
- std::vector<const basic_common_type *> filter(std::distance(from, to));
- std::transform(first, last, component.begin(), [this](const auto ctype) {
- const auto it = std::find_if(pools.cbegin(), pools.cend(), [ctype](auto &&pdata) { return pdata.poly && pdata.poly->value_type().hash() == ctype; });
- return it == pools.cend() ? nullptr : it->pool.get();
- });
- std::transform(from, to, filter.begin(), [this](const auto ctype) {
- const auto it = std::find_if(pools.cbegin(), pools.cend(), [ctype](auto &&pdata) { return pdata.poly && pdata.poly->value_type().hash() == ctype; });
- return it == pools.cend() ? nullptr : it->pool.get();
- });
- return { std::move(component), std::move(filter) };
- }
- /**
- * @brief Returns a group for the given components.
- *
- * This kind of objects are created on the fly and share with the registry
- * its internal data structures.<br/>
- * Feel free to discard a group after the use. Creating and destroying a
- * group is an incredibly cheap operation because they do not require any
- * type of initialization, but for the first time they are requested.<br/>
- * 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, which will consequently be
- * slightly slower (nothing that can be noticed in most cases).
- *
- * @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, exclude_t<Exclude...>, get_t<Get...>, Owned...> 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<Exclude...>, get_t<std::remove_const_t<Get>...>, std::remove_const_t<Owned>...>;
- const auto cpools = std::make_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;
- if(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()) && ...);
- }); it != groups.cend())
- {
- handler = static_cast<handler_type *>(it->group.get());
- }
- if(!handler) {
- 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 {
- ENTT_ASSERT(std::all_of(groups.cbegin(), groups.cend(), [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));
- }), "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)... };
- }
- /**
- * @brief Returns a group for the given components.
- *
- * @sa group
- *
- * @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, exclude_t<Exclude...>, get_t<std::add_const_t<Get>...>, std::add_const_t<Owned>...> group_if_exists(get_t<Get...>, exclude_t<Exclude...> = {}) const {
- if(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()) && ...);
- }); it == groups.cend())
- {
- return {};
- } else {
- using handler_type = group_handler<exclude_t<Exclude...>, get_t<std::remove_const_t<Get>...>, std::remove_const_t<Owned>...>;
- return { static_cast<handler_type *>(it->group.get())->current, *pool_if_exists<std::remove_const_t<Owned>>()... , *pool_if_exists<std::remove_const_t<Get>>()... };
- }
- }
- /**
- * @brief Returns a group for the given components.
- *
- * @sa group
- *
- * @tparam Owned Types of components owned by the group.
- * @tparam Exclude Types of components used to filter the group.
- * @return A newly created group.
- */
- template<typename... Owned, typename... Exclude>
- [[nodiscard]] basic_group<Entity, exclude_t<Exclude...>, get_t<>, Owned...> group(exclude_t<Exclude...> = {}) {
- return group<Owned...>(get_t<>{}, exclude<Exclude...>);
- }
- /**
- * @brief Returns a group for the given components.
- *
- * @sa group_if_exists
- *
- * @tparam Owned Types of components owned by the group.
- * @tparam Exclude Types of components used to filter the group.
- * @return A newly created group.
- */
- template<typename... Owned, typename... Exclude>
- [[nodiscard]] basic_group<Entity, exclude_t<Exclude...>, get_t<>, std::add_const_t<Owned>...> 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 sortable, false
- * otherwise.
- */
- template<typename... Component>
- [[nodiscard]] bool sortable() const {
- return std::none_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, exclude_t<Exclude...>, get_t<Get...>, Owned...> &) ENTT_NOEXCEPT {
- constexpr auto size = sizeof...(Owned) + sizeof...(Get) + sizeof...(Exclude);
- return std::find_if(groups.cbegin(), groups.cend(), [size](const auto &gdata) {
- return (0u + ... + gdata.owned(type_hash<std::remove_const_t<Owned>>::value())) && (size < gdata.size);
- }) == groups.cend();
- }
- /**
- * @brief Sorts the pool of entities for the given component.
- *
- * The order of the elements in a pool is highly affected by assignments
- * of components to entities and deletions. Components are arranged to
- * maximize the performance during iterations and users should not make any
- * assumption on the order.<br/>
- * This function can be used to impose an order to the elements in the pool
- * of the given component. The order is kept valid until a component of the
- * given type is assigned or removed from an entity.
- *
- * 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(const Entity, const Entity);
- * bool(const Component &, const Component &);
- * @endcode
- *
- * Moreover, the comparison function object shall induce a
- * _strict weak ordering_ on the values.
- *
- * The sort function oject 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.
- *
- * The comparison funtion object received by the sort 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(sortable<Component>(), "Cannot sort owned storage");
- assure<Component>()->sort(std::move(compare), std::move(algo), std::forward<Args>(args)...);
- }
- /**
- * @brief Sorts two pools of components in the same way.
- *
- * The order of the elements in a pool is highly affected by assignments
- * of components to entities and deletions. Components are arranged to
- * maximize the performance during iterations and users should not make any
- * assumption on the order.
- *
- * It happens that different pools of components must be sorted the same way
- * because of runtime and/or performance constraints. This function can be
- * used to order a pool of components according to the order between the
- * entities in another pool of components.
- *
- * @b How @b it @b works
- *
- * Being `A` and `B` the two sets where `B` is the master (the one the order
- * of which rules) and `A` is the slave (the one to sort), after a call to
- * this function an iterator for `A` will return the entities according to
- * the following rules:
- *
- * * All the entities in `A` that are also in `B` are returned first
- * according to the order they have in `B`.
- * * All the entities in `A` that are not in `B` are returned in no
- * particular order after all the other entities.
- *
- * Any subsequent change to `B` won't affect the order in `A`.
- *
- * @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(sortable<To>(), "Cannot sort owned storage");
- assure<To>()->respect(*assure<From>());
- }
- /**
- * @brief Visits an entity and returns the type info for its components.
- *
- * The signature of the function should be equivalent to the following:
- *
- * @code{.cpp}
- * void(const type_info);
- * @endcode
- *
- * Returned identifiers are those of the components owned by the entity.
- *
- * @sa type_info
- *
- * @warning
- * It's not specified whether a component attached to or removed from the
- * given entity during the visit is returned or not to the caller.
- *
- * @tparam Func Type of the function object to invoke.
- * @param entity A valid entity identifier.
- * @param func A valid function object.
- */
- template<typename Func>
- void visit(entity_type entity, Func func) const {
- for(auto pos = pools.size(); pos; --pos) {
- if(const auto &pdata = pools[pos-1]; pdata.pool && pdata.pool->contains(entity)) {
- func(pdata.poly->value_type());
- }
- }
- }
- /**
- * @brief Visits a registry and returns the type info for its components.
- *
- * The signature of the function should be equivalent to the following:
- *
- * @code{.cpp}
- * void(const type_info);
- * @endcode
- *
- * Returned identifiers are those of the components managed by the registry.
- *
- * @sa type_info
- *
- * @warning
- * It's not specified whether a component for which a pool is created during
- * the visit is returned or not to the caller.
- *
- * @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 pos = pools.size(); pos; --pos) {
- if(const auto &pdata = pools[pos-1]; pdata.pool) {
- func(pdata.poly->value_type());
- }
- }
- }
- /**
- * @brief Binds an object to the context of the registry.
- *
- * If the value already exists it is overwritten, otherwise a new instance
- * of the given type is created and initialized with the arguments provided.
- *
- * @tparam Type Type of object to set.
- * @tparam Args Types of arguments to use to construct the object.
- * @param args Parameters to use to initialize the value.
- * @return A reference to the newly created object.
- */
- template<typename Type, typename... Args>
- Type & set(Args &&... args) {
- unset<Type>();
- vars.emplace_back(std::in_place_type<Type>, std::forward<Args>(args)...);
- return any_cast<Type &>(vars.back());
- }
- /**
- * @brief Unsets a context variable if it exists.
- * @tparam Type Type of object to set.
- */
- template<typename Type>
- void unset() {
- vars.erase(std::remove_if(vars.begin(), vars.end(), [type = type_id<Type>()](auto &&var) { return var.type() == type; }), vars.end());
- }
- /**
- * @brief Binds an object to the context of the registry.
- *
- * In case the context doesn't contain the given object, the parameters
- * provided are used to construct it.
- *
- * @tparam Type Type of object to set.
- * @tparam Args Types of arguments to use to construct the object.
- * @param args Parameters to use to initialize the object.
- * @return A reference to the object in the context of the registry.
- */
- template<typename Type, typename... Args>
- [[nodiscard]] Type & ctx_or_set(Args &&... args) {
- auto *value = try_ctx<Type>();
- return value ? *value : set<Type>(std::forward<Args>(args)...);
- }
- /**
- * @brief Returns a pointer to an object in the context of the registry.
- * @tparam Type Type of object to get.
- * @return A pointer to the object if it exists in the context of the
- * registry, a null pointer otherwise.
- */
- template<typename Type>
- [[nodiscard]] std::add_const_t<Type> * try_ctx() const {
- auto it = std::find_if(vars.cbegin(), vars.cend(), [type = type_id<Type>()](auto &&var) { return var.type() == type; });
- return it == vars.cend() ? nullptr : any_cast<std::add_const_t<Type>>(&*it);
- }
- /*! @copydoc try_ctx */
- template<typename Type>
- [[nodiscard]] Type * try_ctx() {
- auto it = std::find_if(vars.begin(), vars.end(), [type = type_id<Type>()](auto &&var) { return var.type() == type; });
- return it == vars.end() ? nullptr : any_cast<Type>(&*it);
- }
- /**
- * @brief Returns a reference to an object in the context of the registry.
- *
- * @warning
- * Attempting to get a context variable that doesn't exist results in
- * undefined behavior.
- *
- * @tparam Type Type of object to get.
- * @return A valid reference to the object in the context of the registry.
- */
- template<typename Type>
- [[nodiscard]] std::add_const_t<Type> & ctx() const {
- auto it = std::find_if(vars.cbegin(), vars.cend(), [type = type_id<Type>()](auto &&var) { return var.type() == type; });
- ENTT_ASSERT(it != vars.cend(), "Invalid instance");
- return any_cast<std::add_const_t<Type> &>(*it);
- }
- /*! @copydoc ctx */
- template<typename Type>
- [[nodiscard]] Type & ctx() {
- auto it = std::find_if(vars.begin(), vars.end(), [type = type_id<Type>()](auto &&var) { return var.type() == type; });
- ENTT_ASSERT(it != vars.end(), "Invalid instance");
- return any_cast<Type &>(*it);
- }
- /**
- * @brief Visits a registry and returns the type info for its context
- * variables.
- *
- * The signature of the function should be equivalent to the following:
- *
- * @code{.cpp}
- * void(const type_info);
- * @endcode
- *
- * Returned identifiers are those of the context variables currently set.
- *
- * @sa type_info
- *
- * @warning
- * It's not specified whether a context variable created during the visit is
- * returned or not to the caller.
- *
- * @tparam Func Type of the function object to invoke.
- * @param func A valid function object.
- */
- template<typename Func>
- void ctx(Func func) const {
- for(auto pos = vars.size(); pos; --pos) {
- func(vars[pos-1].type());
- }
- }
- private:
- std::vector<basic_any<0u>> vars{};
- mutable std::vector<pool_data> pools{};
- std::vector<group_data> groups{};
- std::vector<entity_type> entities{};
- entity_type free_list{tombstone};
- };
- }
- #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 An entity identifier.
- */
- basic_handle(registry_type &ref, entity_type value) ENTT_NOEXCEPT
- : reg{&ref}, entt{value}
- {}
- /**
- * @brief Compares two handles.
- * @tparam Args Template parameters of the handle with which to compare.
- * @param other Handle with which to compare.
- * @return True if both handles refer to the same registry and the same
- * entity, false otherwise.
- */
- template<typename... Args>
- [[nodiscard]] bool operator==(const basic_handle<Args...> &other) const ENTT_NOEXCEPT {
- return reg == other.registry() && entt == other.entity();
- }
- /**
- * @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>)
- && (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 An entity 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);
- }
- /*! @copydoc remove */
- template<typename... Component>
- [[deprecated("Use ::remove instead")]]
- size_type remove_if_exists() const {
- return remove<Component...>();
- }
- /**
- * @brief Removes all the components from a handle and makes it orphaned.
- * @sa basic_registry::remove_all
- */
- [[deprecated("No longer supported")]]
- void remove_all() const {
- static_assert(sizeof...(Type) == 0, "Invalid operation");
- reg->remove_all(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 types for its components.
- * @sa basic_registry::visit
- * @tparam Func Type of the function object to invoke.
- * @param func A valid function object.
- */
- template<typename Func>
- void visit(Func &&func) const {
- reg->visit(entt, std::forward<Func>(func));
- }
- private:
- registry_type *reg;
- entity_type entt;
- };
- /**
- * @brief Compares two handles.
- * @tparam Type A valid entity type (see entt_traits for more details).
- * @tparam Other A valid entity type (see entt_traits for more details).
- * @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 Type, typename Other>
- bool operator!=(const basic_handle<Type> &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>;
- }
- #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 <tuple>
- #include <cstddef>
- #include <utility>
- #include <functional>
- #include <type_traits>
- // #include "../core/type_traits.hpp"
- // #include "../config/config.h"
- 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...>{};
- }
- }
- /**
- * 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
- : fn{nullptr}, data{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 {
- data = 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 {
- data = &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 {
- data = 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 {
- fn = function;
- data = payload;
- }
- /**
- * @brief Resets a delegate.
- *
- * After a reset, a delegate cannot be invoked anymore.
- */
- void reset() ENTT_NOEXCEPT {
- fn = nullptr;
- data = 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 * instance() const ENTT_NOEXCEPT {
- return data;
- }
- /**
- * @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(data, 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 test also data
- 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 && data == other.data;
- }
- private:
- function_type *fn;
- const void *data;
- };
- /**
- * @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...)>;
- }
- #endif
- // #include "registry.hpp"
- // #include "fwd.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, Exclude, Component...>() 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 Exclude Types of components used to filter the group.
- * @tparam Get Types of components observed by the group.
- * @tparam Owned Types of components owned by the group.
- * @return A newly created group.
- */
- template<typename Exclude, typename Get, typename... Owned>
- operator basic_group<entity_type, Exclude, Get, Owned...>() 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 view = reg.template view<const Component>();
- const auto *addr = std::addressof(instance);
- for(auto it = view.rbegin(), last = view.rend(); it < last; it += ENTT_PACKED_PAGE) {
- if(const auto dist = (addr - std::addressof(view.template get<const Component>(*it))); dist >= 0 && dist < ENTT_PACKED_PAGE) {
- return *(it + dist);
- }
- }
- return entt::null;
- }
- }
- #endif
- // #include "entity/observer.hpp"
- #ifndef ENTT_ENTITY_OBSERVER_HPP
- #define ENTT_ENTITY_OBSERVER_HPP
- #include <limits>
- #include <cstddef>
- #include <cstdint>
- #include <utility>
- #include <type_traits>
- // #include "../config/config.h"
- // #include "../core/type_traits.hpp"
- // #include "../signal/delegate.hpp"
- // #include "registry.hpp"
- // #include "storage.hpp"
- // #include "utility.hpp"
- // #include "entity.hpp"
- // #include "fwd.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) {
- if([®, 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(!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;
- };
- }
- #endif
- // #include "entity/organizer.hpp"
- #ifndef ENTT_ENTITY_ORGANIZER_HPP
- #define ENTT_ENTITY_ORGANIZER_HPP
- #include <cstddef>
- #include <algorithm>
- #include <type_traits>
- #include <unordered_map>
- #include <utility>
- #include <vector>
- // #include "../core/type_info.hpp"
- // #include "../core/type_traits.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 "registry.hpp"
- // #include "fwd.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, Exclude, Component...>() 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 Exclude Types of components used to filter the group.
- * @tparam Get Types of components observed by the group.
- * @tparam Owned Types of components owned by the group.
- * @return A newly created group.
- */
- template<typename Exclude, typename Get, typename... Owned>
- operator basic_group<entity_type, Exclude, Get, Owned...>() 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 view = reg.template view<const Component>();
- const auto *addr = std::addressof(instance);
- for(auto it = view.rbegin(), last = view.rend(); it < last; it += ENTT_PACKED_PAGE) {
- if(const auto dist = (addr - std::addressof(view.template get<const Component>(*it))); dist >= 0 && dist < ENTT_PACKED_PAGE) {
- return *(it + dist);
- }
- }
- return entt::null;
- }
- }
- #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... Exclude, typename... Component>
- struct is_view<basic_view<Entity, exclude_t<Exclude...>, Component...>>: 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... Exclude, typename... Component, typename... Override>
- struct unpack_type<basic_view<Entity, exclude_t<Exclude...>, Component...>, 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... Exclude, typename... Component, typename... Override>
- struct unpack_type<const basic_view<Entity, exclude_t<Exclude...>, Component...>, type_list<Override...>>
- : unpack_type<basic_view<Entity, exclude_t<Exclude...>, Component...>, type_list<Override...>>
- {};
- template<typename, typename>
- struct resource;
- template<typename... Args, typename... Req>
- struct resource<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<type_list<std::remove_reference_t<Args>...>, type_list<Req...>> free_function_to_resource(Ret(*)(Args...));
- template<typename... Req, typename Ret, typename Type, typename... Args>
- resource<type_list<std::remove_reference_t<Args>...>, type_list<Req...>> constrained_function_to_resource(Ret(*)(Type &, Args...));
- template<typename... Req, typename Ret, typename Class, typename... Args>
- resource<type_list<std::remove_reference_t<Args>...>, type_list<Req...>> constrained_function_to_resource(Ret(Class:: *)(Args...));
- template<typename... Req, typename Ret, typename Class, typename... Args>
- resource<type_list<std::remove_reference_t<Args>...>, type_list<Req...>> constrained_function_to_resource(Ret(Class:: *)(Args...) const);
- template<typename... Req>
- resource<type_list<>, type_list<Req...>> to_resource();
- }
- /**
- * 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 *, entt::basic_registry<Entity> &);
- using prepare_type = void(entt::basic_registry<Entity> &);
- using dependency_type = std::size_t(const bool, 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{};
- 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.template ctx_or_set<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]] type_info *buffer, [[maybe_unused]] const std::size_t count) {
- if constexpr(sizeof...(Type) == 0u) {
- return {};
- } else {
- 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 ajacency 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(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(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.
- */
- 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<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{}));
- };
- track_dependencies(vertices.size(), requires_registry, typename resource_type::ro{}, typename resource_type::rw{});
- vertices.push_back({
- resource_type::ro::size,
- resource_type::rw::size,
- name,
- nullptr,
- callback,
- +[](const bool rw, 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>>()
- });
- }
- /**
- * @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<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{})));
- };
- track_dependencies(vertices.size(), requires_registry, typename resource_type::ro{}, typename resource_type::rw{});
- vertices.push_back({
- resource_type::ro::size,
- resource_type::rw::size,
- name,
- &value_or_instance,
- callback,
- +[](const bool rw, 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>>()
- });
- }
- /**
- * @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<type_list<>, type_list<Req...>>;
- track_dependencies(vertices.size(), true, typename resource_type::ro{}, typename resource_type::rw{});
- vertices.push_back({
- resource_type::ro::size,
- resource_type::rw::size,
- name,
- payload,
- func,
- +[](const bool rw, 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_info{}
- });
- }
- /**
- * @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:
- std::unordered_map<entt::id_type, std::vector<std::pair<std::size_t, bool>>> dependencies;
- std::vector<vertex_data> vertices;
- };
- }
- #endif
- // #include "entity/poly_storage.hpp"
- #ifndef ENTT_ENTITY_POLY_STORAGE_HPP
- #define ENTT_ENTITY_POLY_STORAGE_HPP
- #include <cstddef>
- #include <tuple>
- // #include "../core/type_info.hpp"
- // #include "../core/type_traits.hpp"
- // #include "../poly/poly.hpp"
- // #include "fwd.hpp"
- namespace entt {
- /**
- * @brief Basic poly storage implementation.
- * @tparam Entity A valid entity type (see entt_traits for more details).
- */
- template<typename Entity>
- struct Storage: type_list<type_info() const ENTT_NOEXCEPT> {
- /**
- * @brief Concept definition.
- * @tparam Base Opaque base class from which to inherit.
- */
- template<typename Base>
- struct type: Base {
- /**
- * @brief Returns a type info for the contained objects.
- * @return The type info for the contained objects.
- */
- type_info value_type() const ENTT_NOEXCEPT {
- return poly_call<0>(*this);
- }
- };
- /**
- * @brief Concept implementation.
- * @tparam Type Type for which to generate an implementation.
- */
- template<typename Type>
- using impl = value_list<&type_id<typename Type::value_type>>;
- };
- /**
- * @brief Defines the poly storage type associate with a given entity type.
- * @tparam Entity A valid entity type (see entt_traits for more details).
- */
- template<typename Entity, typename = void>
- struct poly_storage_traits {
- /*! @brief Poly storage type for the given entity type. */
- using storage_type = poly<Storage<Entity>>;
- };
- }
- #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 "../core/algorithm.hpp"
- // #include "../core/any.hpp"
- // #include "../core/fwd.hpp"
- // #include "../core/type_info.hpp"
- // #include "../core/type_traits.hpp"
- // #include "component.hpp"
- // #include "entity.hpp"
- // #include "fwd.hpp"
- // #include "group.hpp"
- // #include "poly_storage.hpp"
- // #include "runtime_view.hpp"
- // #include "sparse_set.hpp"
- // #include "storage.hpp"
- // #include "utility.hpp"
- // #include "view.hpp"
- namespace entt {
- /**
- * @brief Fast and reliable entity-component system.
- *
- * The registry is the core class of the entity-component framework.<br/>
- * It stores entities and arranges pools of components on a per request basis.
- * By means of a registry, users can manage entities and components, then create
- * views or groups to iterate them.
- *
- * @tparam Entity A valid entity type (see entt_traits for more details).
- */
- template<typename Entity>
- class basic_registry {
- using traits_type = entt_traits<Entity>;
- using poly_storage_type = typename poly_storage_traits<Entity>::storage_type;
- using basic_common_type = basic_sparse_set<Entity>;
- template<typename Component>
- using storage_type = constness_as_t<typename storage_traits<Entity, std::remove_const_t<Component>>::storage_type, Component>;
- struct pool_data {
- poly_storage_type poly;
- std::unique_ptr<basic_common_type> pool{};
- };
- template<typename...>
- struct group_handler;
- template<typename... Exclude, typename... Get, typename... Owned>
- struct group_handler<exclude_t<Exclude...>, get_t<Get...>, Owned...> {
- static_assert(!std::disjunction_v<typename component_traits<Owned>::in_place_delete...>, "Groups do not support in-place delete");
- static_assert(std::conjunction_v<std::is_same<Owned, std::remove_const_t<Owned>>..., std::is_same<Get, std::remove_const_t<Get>>..., std::is_same<Exclude, std::remove_const_t<Exclude>>...>, "One or more component types are invalid");
- 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::make_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(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::make_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(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]] storage_type<Component> * assure() const {
- static_assert(std::is_same_v<Component, std::decay_t<Component>>, "Non-decayed types not allowed");
- const auto index = type_seq<Component>::value();
- if(!(index < pools.size())) {
- pools.resize(size_type(index)+1u);
- }
- if(auto &&pdata = pools[index]; !pdata.pool) {
- pdata.pool.reset(new storage_type<Component>());
- pdata.poly.template emplace<storage_type<Component> &>(*static_cast<storage_type<Component> *>(pdata.pool.get()));
- }
- return static_cast<storage_type<Component> *>(pools[index].pool.get());
- }
- template<typename Component>
- [[nodiscard]] const storage_type<Component> * pool_if_exists() const ENTT_NOEXCEPT {
- static_assert(std::is_same_v<Component, std::decay_t<Component>>, "Non-decayed types not allowed");
- const auto index = type_seq<Component>::value();
- return (!(index < pools.size()) || !pools[index].pool) ? nullptr : static_cast<const storage_type<Component> *>(pools[index].pool.get());
- }
- auto generate_identifier(const std::size_t pos) ENTT_NOEXCEPT {
- ENTT_ASSERT(pos < traits_type::to_integral(null), "No entities available");
- return traits_type::construct(static_cast<typename traits_type::entity_type>(pos), {});
- }
- auto recycle_identifier() ENTT_NOEXCEPT {
- ENTT_ASSERT(free_list != null, "No entities available");
- const auto curr = traits_type::to_entity(free_list);
- free_list = (tombstone | entities[curr]);
- return (entities[curr] = traits_type::construct(curr, traits_type::to_version(entities[curr])));
- }
- auto release_entity(const Entity entity, const typename traits_type::version_type version) {
- const typename traits_type::version_type vers = version + (version == traits_type::to_version(tombstone));
- entities[traits_type::to_entity(entity)] = traits_type::construct(traits_type::to_entity(free_list), vers);
- free_list = (tombstone | entity);
- return vers;
- }
- public:
- /*! @brief Underlying entity identifier. */
- using entity_type = Entity;
- /*! @brief Underlying version type. */
- using version_type = typename traits_type::version_type;
- /*! @brief Unsigned integer type. */
- using size_type = std::size_t;
- /*! @brief Poly storage type. */
- using poly_storage = typename poly_storage_traits<Entity>::storage_type;
- /**
- * @brief Returns the entity identifier without the version.
- * @param entity An entity identifier, either valid or not.
- * @return The entity identifier without the version.
- */
- [[nodiscard]] static entity_type entity(const entity_type entity) ENTT_NOEXCEPT {
- return traits_type::construct(traits_type::to_entity(entity), {});
- }
- /**
- * @brief Returns the version stored along with an entity identifier.
- * @param entity An entity identifier, either valid or not.
- * @return The version stored along with the given entity identifier.
- */
- [[nodiscard]] static version_type version(const entity_type entity) ENTT_NOEXCEPT {
- return traits_type::to_version(entity);
- }
- /*! @brief Default constructor. */
- basic_registry() = default;
- /*! @brief Default move constructor. */
- basic_registry(basic_registry &&) = default;
- /*! @brief Default move assignment operator. @return This registry. */
- basic_registry & operator=(basic_registry &&) = default;
- /**
- * @brief Prepares a pool for the given type if required.
- * @tparam Component Type of component for which to prepare a pool.
- */
- template<typename Component>
- void prepare() {
- // suppress the warning due to the [[nodiscard]] attribute
- static_cast<void>(assure<Component>());
- }
- /**
- * @brief Returns a poly storage for a given type.
- * @param info The type for which to return a poly storage.
- * @return A valid poly storage if a pool for the given type exists, an
- * empty and thus invalid element otherwise.
- */
- poly_storage & storage(const type_info info) {
- ENTT_ASSERT(info.seq() < pools.size() && pools[info.seq()].poly, "Storage not available");
- return pools[info.seq()].poly;
- }
- /*! @copydoc storage */
- const poly_storage & storage(const type_info info) const {
- ENTT_ASSERT(info.seq() < pools.size() && pools[info.seq()].poly, "Storage not available");
- return pools[info.seq()].poly;
- }
- /**
- * @brief Returns the number of existing components of the given type.
- * @tparam Component Type of component of which to return the size.
- * @return Number of existing components of the given type.
- */
- template<typename Component>
- [[nodiscard]] size_type size() const {
- const auto *cpool = pool_if_exists<Component>();
- return cpool ? cpool->size() : size_type{};
- }
- /**
- * @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[traits_type::to_entity(curr)];
- }
- return sz;
- }
- /**
- * @brief Increases the capacity of the registry or of the pools for the
- * given components.
- *
- * If no components are specified, the capacity of the registry is
- * increased, that is the number of entities it contains. Otherwise the
- * capacity of the pools for the given components is increased.<br/>
- * In both cases, if the new capacity is greater than the current capacity,
- * new storage is allocated, otherwise the method does nothing.
- *
- * @tparam Component Types of components for which to reserve storage.
- * @param cap Desired capacity.
- */
- template<typename... Component>
- void reserve(const size_type cap) {
- if constexpr(sizeof...(Component) == 0) {
- entities.reserve(cap);
- } else {
- (assure<Component>()->reserve(cap), ...);
- }
- }
- /**
- * @brief Reserves enough space to store `count` pools.
- * @param count Number of pools to reserve space for.
- */
- [[deprecated("No longer supported")]]
- void reserve_pools(const size_t count) {
- pools.reserve(count);
- }
- /**
- * @brief Returns the capacity of the pool for the given component.
- * @tparam Component Type of component in which one is interested.
- * @return Capacity of the pool of the given component.
- */
- template<typename Component>
- [[nodiscard]] size_type capacity() const {
- const auto *cpool = pool_if_exists<Component>();
- return cpool ? cpool->capacity() : size_type{};
- }
- /**
- * @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 Requests the removal of unused capacity for the given components.
- * @tparam Component Types of components for which to reclaim unused
- * capacity.
- */
- template<typename... Component>
- void shrink_to_fit() {
- (assure<Component>()->shrink_to_fit(), ...);
- }
- /**
- * @brief Checks whether the registry or the pools of the given components
- * are empty.
- *
- * A registry is considered empty when it doesn't contain entities that are
- * still in use.
- *
- * @tparam Component Types of components in which one is interested.
- * @return True if the registry or the pools of the given components are
- * empty, false otherwise.
- */
- template<typename... Component>
- [[nodiscard]] bool empty() const {
- if constexpr(sizeof...(Component) == 0) {
- return !alive();
- } else {
- return [](const auto *... cpool) { return ((!cpool || cpool->empty()) && ...); }(pool_if_exists<Component>()...);
- }
- }
- /**
- * @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 container 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;
- }
- /*! @copydoc released */
- [[deprecated("Use ::released instead")]]
- [[nodiscard]] entity_type destroyed() const ENTT_NOEXCEPT {
- return released();
- }
- /**
- * @brief Checks if an entity identifier refers to a valid entity.
- * @param entity An entity 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(traits_type::to_entity(entity));
- return (pos < entities.size() && entities[pos] == entity);
- }
- /**
- * @brief Returns the actual version for an entity identifier.
- *
- * @warning
- * Attempting to use an entity that doesn't belong to the registry results
- * in undefined behavior. An entity belongs to the registry even if it has
- * been previously destroyed and/or recycled.
- *
- * @param entity A valid entity identifier.
- * @return Actual version for the given entity identifier.
- */
- [[nodiscard]] version_type current(const entity_type entity) const {
- const auto pos = size_type(traits_type::to_entity(entity));
- ENTT_ASSERT(pos < entities.size(), "Entity does not exist");
- return version(entities[pos]);
- }
- /**
- * @brief Creates a new entity and returns it.
- *
- * There are two kinds of possible entity identifiers:
- *
- * * Newly created ones in case no entities have been previously destroyed.
- * * Recycled ones with updated versions.
- *
- * @return A valid entity identifier.
- */
- [[nodiscard]] entity_type create() {
- return (free_list == null) ? entities.emplace_back(generate_identifier(entities.size())) : recycle_identifier();
- }
- /**
- * @brief Creates a new entity and returns it.
- *
- * @sa create
- *
- * If the requested entity isn't in use, the suggested identifier is created
- * and returned. Otherwise, a new identifier is generated.
- *
- * @param hint Required entity identifier.
- * @return A valid entity 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 = traits_type::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 = traits_type::to_entity(entities[req]); req == curr) {
- return create();
- } else {
- auto *it = &free_list;
- for(; traits_type::to_entity(*it) != req; it = &entities[traits_type::to_entity(*it)]);
- *it = traits_type::construct(curr, traits_type::to_version(*it));
- return (entities[req] = hint);
- }
- }
- /**
- * @brief Assigns each element in a range an entity.
- *
- * @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 entities 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 entity 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 entity identifier.
- * @return The version of the recycled entity.
- */
- version_type release(const entity_type entity) {
- return release(entity, version(entity) + 1u);
- }
- /**
- * @brief Releases an entity 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 entity 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 entity 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, version(*first) + 1u);
- }
- }
- /**
- * @brief Destroys an entity and releases its identifier.
- *
- * The version is updated and the identifier can be recycled at any time.
- *
- * @warning
- * Adding or removing components to an entity that is being destroyed can
- * result in undefined behavior.
- *
- * @warning
- * Attempting to use an invalid entity results in undefined behavior.
- *
- * @param entity A valid entity identifier.
- * @return The version of the recycled entity.
- */
- version_type destroy(const entity_type entity) {
- return destroy(entity, 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 entity 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(auto &&pdata: pools) {
- pdata.pool && pdata.pool->remove(entity, this);
- }
- 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) {
- if constexpr(is_iterator_type_v<typename basic_common_type::iterator, It>) {
- for(; first != last; ++first) {
- destroy(*first, version(*first) + 1u);
- }
- } else {
- for(auto &&pdata: pools) {
- pdata.pool && pdata.pool->remove(first, last, this);
- }
- release(first, last);
- }
- }
- /**
- * @brief Assigns the given component to an entity.
- *
- * A new instance of the given component is created and initialized with the
- * arguments provided (the component must have a proper constructor or be of
- * aggregate type). Then the component is assigned to the given entity.
- *
- * @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 entity 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(*this, 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(*this, 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<std::decay_t<typename std::iterator_traits<CIt>::value_type>, Component>>>
- void insert(EIt first, EIt last, CIt from) {
- static_assert(std::is_constructible_v<Component, typename std::iterator_traits<CIt>::value_type>, "Invalid value type");
- ENTT_ASSERT(std::all_of(first, last, [this](const auto entity) { return valid(entity); }), "Invalid entity");
- assure<Component>()->insert(*this, first, last, from);
- }
- /**
- * @brief Assigns or replaces the given component for an entity.
- *
- * Equivalent to the following snippet (pseudocode):
- *
- * @code{.cpp}
- * auto &component = registry.all_of<Component>(entity) ? registry.replace<Component>(entity, args...) : registry.emplace<Component>(entity, args...);
- * @endcode
- *
- * Prefer this function anyway because it has slightly better performance.
- *
- * @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 entity 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(*this, entity, [&args...](auto &... curr) { ((curr = Component{std::forward<Args>(args)...}), ...); })
- : cpool->emplace(*this, entity, std::forward<Args>(args)...);
- }
- /**
- * @brief Patches the given component for an entity.
- *
- * The signature of the functions 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 entity 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(*this, entity, std::forward<Func>(func)...);
- }
- /**
- * @brief Replaces the given component for an entity.
- *
- * A new instance of the given component is created and initialized with the
- * arguments provided (the component must have a proper constructor or be of
- * aggregate type). Then the component is assigned to the given entity.
- *
- * @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 entity 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) {
- return assure<Component>()->patch(*this, 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 Types of components to remove.
- * @param entity A valid entity identifier.
- * @return The number of components actually removed.
- */
- template<typename... Component>
- size_type remove(const entity_type entity) {
- ENTT_ASSERT(valid(entity), "Invalid entity");
- static_assert(sizeof...(Component) > 0, "Provide one or more component types");
- return (assure<Component>()->remove(entity, this) + ... + size_type{});
- }
- /**
- * @brief Removes the given components from all the entities in a range.
- *
- * @sa remove
- *
- * @tparam Component 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 It>
- size_type remove(It first, It last) {
- static_assert(sizeof...(Component) > 0, "Provide one or more component types");
- const auto cpools = std::make_tuple(assure<Component>()...);
- size_type count{};
- for(; first != last; ++first) {
- const auto entity = *first;
- ENTT_ASSERT(valid(entity), "Invalid entity");
- count += (std::get<storage_type<Component> *>(cpools)->remove(entity, this) + ...);
- }
- 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.
- * @param entity A valid entity identifier.
- */
- template<typename... Component>
- void erase(const entity_type entity) {
- ENTT_ASSERT(valid(entity), "Invalid entity");
- static_assert(sizeof...(Component) > 0, "Provide one or more component types");
- (assure<Component>()->erase(entity, this), ...);
- }
- /**
- * @brief Erases the given components from all the entities in a range.
- *
- * @sa erase
- *
- * @tparam Component 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 It>
- void erase(It first, It last) {
- static_assert(sizeof...(Component) > 0, "Provide one or more component types");
- const auto cpools = std::make_tuple(assure<Component>()...);
- for(; first != last; ++first) {
- const auto entity = *first;
- ENTT_ASSERT(valid(entity), "Invalid entity");
- (std::get<storage_type<Component> *>(cpools)->erase(entity, this), ...);
- }
- }
- /**
- * @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 &&pdata: pools) {
- pdata.pool && (pdata.pool->compact(), true);
- }
- } else {
- (assure<Component>()->compact(), ...);
- }
- }
- /*! @copydoc remove */
- template<typename... Component>
- [[deprecated("Use ::remove instead")]]
- size_type remove_if_exists(const entity_type entity) {
- return remove<Component...>(entity);
- }
- /**
- * @brief Removes all the components from an entity and makes it orphaned.
- *
- * @warning
- * In case there are listeners that observe the destruction of components
- * and assign other components to the entity in their bodies, the result of
- * invoking this function may not be as expected. In the worst case, it
- * could lead to undefined behavior.
- *
- * @warning
- * Attempting to use an invalid entity results in undefined behavior.
- *
- * @param entity A valid entity identifier.
- */
- [[deprecated("Use ::destroy(entity)/::create(entity) instead")]]
- void remove_all(const entity_type entity) {
- ENTT_ASSERT(valid(entity), "Invalid entity");
- for(auto &&pdata: pools) {
- pdata.pool && pdata.pool->remove(entity, this);
- }
- }
- /**
- * @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 entity 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 [entity](const auto *... cpool) { return ((cpool && cpool->contains(entity)) && ...); }(pool_if_exists<Component>()...);
- }
- /**
- * @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 entity 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 [entity](const auto *... cpool) { return !((!cpool || !cpool->contains(entity)) && ...); }(pool_if_exists<Component>()...);
- }
- /**
- * @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 entity 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");
- if constexpr(sizeof...(Component) == 1) {
- const auto *cpool = pool_if_exists<std::remove_const_t<Component>...>();
- ENTT_ASSERT(cpool, "Storage not available");
- return cpool->get(entity);
- } else {
- return std::forward_as_tuple(get<Component>(entity)...);
- }
- }
- /*! @copydoc get */
- template<typename... Component>
- [[nodiscard]] decltype(auto) get([[maybe_unused]] const entity_type entity) {
- ENTT_ASSERT(valid(entity), "Invalid entity");
- if constexpr(sizeof...(Component) == 1) {
- return (const_cast<Component &>(assure<std::remove_const_t<Component>>()->get(entity)), ...);
- } else {
- return std::forward_as_tuple(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.<br/>
- * Equivalent to the following snippet (pseudocode):
- *
- * @code{.cpp}
- * auto &component = registry.all_of<Component>(entity) ? registry.get<Component>(entity) : registry.emplace<Component>(entity, args...);
- * @endcode
- *
- * Prefer this function anyway because it has slightly better performance.
- *
- * @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 entity 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(*this, 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 entity 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 = pool_if_exists<std::remove_const_t<Component>...>();
- return (cpool && cpool->contains(entity)) ? &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) {
- ENTT_ASSERT(valid(entity), "Invalid 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 &&pdata: pools) {
- pdata.pool && (pdata.pool->clear(this), true);
- }
- each([this](const auto entity) { release_entity(entity, version(entity) + 1u); });
- } else {
- (assure<Component>()->clear(this), ...);
- }
- }
- /**
- * @brief Iterates all the entities that are still in use.
- *
- * The function object is invoked for each entity that is still in use.<br/>
- * The signature of the function should be equivalent to the following:
- *
- * @code{.cpp}
- * void(const Entity);
- * @endcode
- *
- * This function is fairly slow and should not be used frequently. However,
- * it's useful for iterating all the entities still in use, regardless of
- * their components.
- *
- * @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]; traits_type::to_entity(entity) == (pos - 1)) {
- func(entity);
- }
- }
- }
- }
- /**
- * @brief Checks if an entity has components assigned.
- * @param entity A valid entity 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 &&pdata) { return pdata.pool && pdata.pool->contains(entity); });
- }
- /**
- * @brief Iterates orphans and applies them the given function object.
- *
- * The function object is invoked for each entity that is still in use and
- * has no components assigned.<br/>
- * The signature of the function should be equivalent to the following:
- *
- * @code{.cpp}
- * void(const Entity);
- * @endcode
- *
- * This function can be very slow and should not be used frequently.
- *
- * @tparam Func Type of the function object to invoke.
- * @param func A valid function object.
- */
- template<typename Func>
- void orphans(Func func) const {
- each([this, &func](const auto entity) {
- if(orphan(entity)) {
- func(entity);
- }
- });
- }
- /**
- * @brief Returns a sink object for the given component.
- *
- * The sink returned by this function can be used 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** the component has been assigned 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.
- *
- * The sink returned by this function can be used 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** the component has been updated.
- *
- * @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.
- *
- * The sink returned by this function can be used 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** the component has been removed 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.
- *
- * This kind of objects are created on the fly and share with the registry
- * its internal data structures.<br/>
- * Feel free to discard a view after the use. Creating and destroying a view
- * is an incredibly cheap operation because they do not require any type of
- * initialization.<br/>
- * As a rule of thumb, storing a view should never be an option.
- *
- * Views do their best to iterate the smallest set of candidate entities.
- * In particular:
- *
- * * Single component views are incredibly fast and iterate a packed array
- * of entities, all of which has the given component.
- * * Multi component views look at the number of entities available for each
- * component and pick up a reference to the smallest set of candidates to
- * test for the given components.
- *
- * Views in no way affect the functionalities of the registry nor those of
- * the underlying pools.
- *
- * @note
- * Multi component views are pretty fast. However their performance tend to
- * degenerate when the number of components to iterate grows up and the most
- * of the entities have all the given components.<br/>
- * To get a performance boost, consider using a group instead.
- *
- * @tparam Component Type 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... Exclude>
- [[nodiscard]] basic_view<Entity, exclude_t<Exclude...>, std::add_const_t<Component>...> view(exclude_t<Exclude...> = {}) const {
- static_assert(sizeof...(Component) > 0, "Exclusion-only views are not supported");
- return { *assure<std::remove_const_t<Component>>()..., *assure<Exclude>()... };
- }
- /*! @copydoc view */
- template<typename... Component, typename... Exclude>
- [[nodiscard]] basic_view<Entity, exclude_t<Exclude...>, Component...> view(exclude_t<Exclude...> = {}) {
- static_assert(sizeof...(Component) > 0, "Exclusion-only views are not supported");
- return { *assure<std::remove_const_t<Component>>()..., *assure<Exclude>()... };
- }
- /**
- * @brief Returns a runtime view for the given components.
- *
- * This kind of objects are created on the fly and share with the registry
- * its internal data structures.<br/>
- * Users should throw away the view after use. Fortunately, creating and
- * destroying a runtime view is an incredibly cheap operation because they
- * do not require any type of initialization.<br/>
- * As a rule of thumb, storing a view should never be an option.
- *
- * Runtime views are to be used when users want to construct a view from
- * some external inputs and don't know at compile-time what are the required
- * components.
- *
- * @tparam ItComp Type of input iterator for the components to use to
- * construct the view.
- * @tparam ItExcl Type of input iterator for the components to use to filter
- * the view.
- * @param first An iterator to the first element of the range of components
- * to use to construct the view.
- * @param last An iterator past the last element of the range of components
- * to use to construct the view.
- * @param from An iterator to the first element of the range of components
- * to use to filter the view.
- * @param to An iterator past the last element of the range of components to
- * use to filter the view.
- * @return A newly created runtime view.
- */
- template<typename ItComp, typename ItExcl = id_type *>
- [[nodiscard]] basic_runtime_view<Entity> runtime_view(ItComp first, ItComp last, ItExcl from = {}, ItExcl to = {}) const {
- std::vector<const basic_common_type *> component(std::distance(first, last));
- std::vector<const basic_common_type *> filter(std::distance(from, to));
- std::transform(first, last, component.begin(), [this](const auto ctype) {
- const auto it = std::find_if(pools.cbegin(), pools.cend(), [ctype](auto &&pdata) { return pdata.poly && pdata.poly->value_type().hash() == ctype; });
- return it == pools.cend() ? nullptr : it->pool.get();
- });
- std::transform(from, to, filter.begin(), [this](const auto ctype) {
- const auto it = std::find_if(pools.cbegin(), pools.cend(), [ctype](auto &&pdata) { return pdata.poly && pdata.poly->value_type().hash() == ctype; });
- return it == pools.cend() ? nullptr : it->pool.get();
- });
- return { std::move(component), std::move(filter) };
- }
- /**
- * @brief Returns a group for the given components.
- *
- * This kind of objects are created on the fly and share with the registry
- * its internal data structures.<br/>
- * Feel free to discard a group after the use. Creating and destroying a
- * group is an incredibly cheap operation because they do not require any
- * type of initialization, but for the first time they are requested.<br/>
- * 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, which will consequently be
- * slightly slower (nothing that can be noticed in most cases).
- *
- * @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, exclude_t<Exclude...>, get_t<Get...>, Owned...> 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<Exclude...>, get_t<std::remove_const_t<Get>...>, std::remove_const_t<Owned>...>;
- const auto cpools = std::make_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;
- if(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()) && ...);
- }); it != groups.cend())
- {
- handler = static_cast<handler_type *>(it->group.get());
- }
- if(!handler) {
- 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 {
- ENTT_ASSERT(std::all_of(groups.cbegin(), groups.cend(), [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));
- }), "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)... };
- }
- /**
- * @brief Returns a group for the given components.
- *
- * @sa group
- *
- * @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, exclude_t<Exclude...>, get_t<std::add_const_t<Get>...>, std::add_const_t<Owned>...> group_if_exists(get_t<Get...>, exclude_t<Exclude...> = {}) const {
- if(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()) && ...);
- }); it == groups.cend())
- {
- return {};
- } else {
- using handler_type = group_handler<exclude_t<Exclude...>, get_t<std::remove_const_t<Get>...>, std::remove_const_t<Owned>...>;
- return { static_cast<handler_type *>(it->group.get())->current, *pool_if_exists<std::remove_const_t<Owned>>()... , *pool_if_exists<std::remove_const_t<Get>>()... };
- }
- }
- /**
- * @brief Returns a group for the given components.
- *
- * @sa group
- *
- * @tparam Owned Types of components owned by the group.
- * @tparam Exclude Types of components used to filter the group.
- * @return A newly created group.
- */
- template<typename... Owned, typename... Exclude>
- [[nodiscard]] basic_group<Entity, exclude_t<Exclude...>, get_t<>, Owned...> group(exclude_t<Exclude...> = {}) {
- return group<Owned...>(get_t<>{}, exclude<Exclude...>);
- }
- /**
- * @brief Returns a group for the given components.
- *
- * @sa group_if_exists
- *
- * @tparam Owned Types of components owned by the group.
- * @tparam Exclude Types of components used to filter the group.
- * @return A newly created group.
- */
- template<typename... Owned, typename... Exclude>
- [[nodiscard]] basic_group<Entity, exclude_t<Exclude...>, get_t<>, std::add_const_t<Owned>...> 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 sortable, false
- * otherwise.
- */
- template<typename... Component>
- [[nodiscard]] bool sortable() const {
- return std::none_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, exclude_t<Exclude...>, get_t<Get...>, Owned...> &) ENTT_NOEXCEPT {
- constexpr auto size = sizeof...(Owned) + sizeof...(Get) + sizeof...(Exclude);
- return std::find_if(groups.cbegin(), groups.cend(), [size](const auto &gdata) {
- return (0u + ... + gdata.owned(type_hash<std::remove_const_t<Owned>>::value())) && (size < gdata.size);
- }) == groups.cend();
- }
- /**
- * @brief Sorts the pool of entities for the given component.
- *
- * The order of the elements in a pool is highly affected by assignments
- * of components to entities and deletions. Components are arranged to
- * maximize the performance during iterations and users should not make any
- * assumption on the order.<br/>
- * This function can be used to impose an order to the elements in the pool
- * of the given component. The order is kept valid until a component of the
- * given type is assigned or removed from an entity.
- *
- * 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(const Entity, const Entity);
- * bool(const Component &, const Component &);
- * @endcode
- *
- * Moreover, the comparison function object shall induce a
- * _strict weak ordering_ on the values.
- *
- * The sort function oject 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.
- *
- * The comparison funtion object received by the sort 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(sortable<Component>(), "Cannot sort owned storage");
- assure<Component>()->sort(std::move(compare), std::move(algo), std::forward<Args>(args)...);
- }
- /**
- * @brief Sorts two pools of components in the same way.
- *
- * The order of the elements in a pool is highly affected by assignments
- * of components to entities and deletions. Components are arranged to
- * maximize the performance during iterations and users should not make any
- * assumption on the order.
- *
- * It happens that different pools of components must be sorted the same way
- * because of runtime and/or performance constraints. This function can be
- * used to order a pool of components according to the order between the
- * entities in another pool of components.
- *
- * @b How @b it @b works
- *
- * Being `A` and `B` the two sets where `B` is the master (the one the order
- * of which rules) and `A` is the slave (the one to sort), after a call to
- * this function an iterator for `A` will return the entities according to
- * the following rules:
- *
- * * All the entities in `A` that are also in `B` are returned first
- * according to the order they have in `B`.
- * * All the entities in `A` that are not in `B` are returned in no
- * particular order after all the other entities.
- *
- * Any subsequent change to `B` won't affect the order in `A`.
- *
- * @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(sortable<To>(), "Cannot sort owned storage");
- assure<To>()->respect(*assure<From>());
- }
- /**
- * @brief Visits an entity and returns the type info for its components.
- *
- * The signature of the function should be equivalent to the following:
- *
- * @code{.cpp}
- * void(const type_info);
- * @endcode
- *
- * Returned identifiers are those of the components owned by the entity.
- *
- * @sa type_info
- *
- * @warning
- * It's not specified whether a component attached to or removed from the
- * given entity during the visit is returned or not to the caller.
- *
- * @tparam Func Type of the function object to invoke.
- * @param entity A valid entity identifier.
- * @param func A valid function object.
- */
- template<typename Func>
- void visit(entity_type entity, Func func) const {
- for(auto pos = pools.size(); pos; --pos) {
- if(const auto &pdata = pools[pos-1]; pdata.pool && pdata.pool->contains(entity)) {
- func(pdata.poly->value_type());
- }
- }
- }
- /**
- * @brief Visits a registry and returns the type info for its components.
- *
- * The signature of the function should be equivalent to the following:
- *
- * @code{.cpp}
- * void(const type_info);
- * @endcode
- *
- * Returned identifiers are those of the components managed by the registry.
- *
- * @sa type_info
- *
- * @warning
- * It's not specified whether a component for which a pool is created during
- * the visit is returned or not to the caller.
- *
- * @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 pos = pools.size(); pos; --pos) {
- if(const auto &pdata = pools[pos-1]; pdata.pool) {
- func(pdata.poly->value_type());
- }
- }
- }
- /**
- * @brief Binds an object to the context of the registry.
- *
- * If the value already exists it is overwritten, otherwise a new instance
- * of the given type is created and initialized with the arguments provided.
- *
- * @tparam Type Type of object to set.
- * @tparam Args Types of arguments to use to construct the object.
- * @param args Parameters to use to initialize the value.
- * @return A reference to the newly created object.
- */
- template<typename Type, typename... Args>
- Type & set(Args &&... args) {
- unset<Type>();
- vars.emplace_back(std::in_place_type<Type>, std::forward<Args>(args)...);
- return any_cast<Type &>(vars.back());
- }
- /**
- * @brief Unsets a context variable if it exists.
- * @tparam Type Type of object to set.
- */
- template<typename Type>
- void unset() {
- vars.erase(std::remove_if(vars.begin(), vars.end(), [type = type_id<Type>()](auto &&var) { return var.type() == type; }), vars.end());
- }
- /**
- * @brief Binds an object to the context of the registry.
- *
- * In case the context doesn't contain the given object, the parameters
- * provided are used to construct it.
- *
- * @tparam Type Type of object to set.
- * @tparam Args Types of arguments to use to construct the object.
- * @param args Parameters to use to initialize the object.
- * @return A reference to the object in the context of the registry.
- */
- template<typename Type, typename... Args>
- [[nodiscard]] Type & ctx_or_set(Args &&... args) {
- auto *value = try_ctx<Type>();
- return value ? *value : set<Type>(std::forward<Args>(args)...);
- }
- /**
- * @brief Returns a pointer to an object in the context of the registry.
- * @tparam Type Type of object to get.
- * @return A pointer to the object if it exists in the context of the
- * registry, a null pointer otherwise.
- */
- template<typename Type>
- [[nodiscard]] std::add_const_t<Type> * try_ctx() const {
- auto it = std::find_if(vars.cbegin(), vars.cend(), [type = type_id<Type>()](auto &&var) { return var.type() == type; });
- return it == vars.cend() ? nullptr : any_cast<std::add_const_t<Type>>(&*it);
- }
- /*! @copydoc try_ctx */
- template<typename Type>
- [[nodiscard]] Type * try_ctx() {
- auto it = std::find_if(vars.begin(), vars.end(), [type = type_id<Type>()](auto &&var) { return var.type() == type; });
- return it == vars.end() ? nullptr : any_cast<Type>(&*it);
- }
- /**
- * @brief Returns a reference to an object in the context of the registry.
- *
- * @warning
- * Attempting to get a context variable that doesn't exist results in
- * undefined behavior.
- *
- * @tparam Type Type of object to get.
- * @return A valid reference to the object in the context of the registry.
- */
- template<typename Type>
- [[nodiscard]] std::add_const_t<Type> & ctx() const {
- auto it = std::find_if(vars.cbegin(), vars.cend(), [type = type_id<Type>()](auto &&var) { return var.type() == type; });
- ENTT_ASSERT(it != vars.cend(), "Invalid instance");
- return any_cast<std::add_const_t<Type> &>(*it);
- }
- /*! @copydoc ctx */
- template<typename Type>
- [[nodiscard]] Type & ctx() {
- auto it = std::find_if(vars.begin(), vars.end(), [type = type_id<Type>()](auto &&var) { return var.type() == type; });
- ENTT_ASSERT(it != vars.end(), "Invalid instance");
- return any_cast<Type &>(*it);
- }
- /**
- * @brief Visits a registry and returns the type info for its context
- * variables.
- *
- * The signature of the function should be equivalent to the following:
- *
- * @code{.cpp}
- * void(const type_info);
- * @endcode
- *
- * Returned identifiers are those of the context variables currently set.
- *
- * @sa type_info
- *
- * @warning
- * It's not specified whether a context variable created during the visit is
- * returned or not to the caller.
- *
- * @tparam Func Type of the function object to invoke.
- * @param func A valid function object.
- */
- template<typename Func>
- void ctx(Func func) const {
- for(auto pos = vars.size(); pos; --pos) {
- func(vars[pos-1].type());
- }
- }
- private:
- std::vector<basic_any<0u>> vars{};
- mutable std::vector<pool_data> pools{};
- std::vector<group_data> groups{};
- std::vector<entity_type> entities{};
- entity_type free_list{tombstone};
- };
- }
- #endif
- // #include "entity/runtime_view.hpp"
- #ifndef ENTT_ENTITY_RUNTIME_VIEW_HPP
- #define ENTT_ENTITY_RUNTIME_VIEW_HPP
- #include <iterator>
- #include <vector>
- #include <utility>
- #include <algorithm>
- #include <type_traits>
- // #include "../config/config.h"
- // #include "entity.hpp"
- // #include "sparse_set.hpp"
- // #include "fwd.hpp"
- namespace entt {
- /**
- * @brief 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).
- */
- template<typename Entity>
- class basic_runtime_view final {
- using basic_common_type = basic_sparse_set<Entity>;
- using underlying_iterator = typename basic_common_type::iterator;
- class view_iterator final {
- [[nodiscard]] bool valid() const {
- const auto entt = *it;
- return (!stable_storage || (entt != tombstone))
- && std::all_of(pools->begin()++, pools->end(), [entt](const auto *curr) { return curr->contains(entt); })
- && std::none_of(filter->cbegin(), filter->cend(), [entt](const auto *curr) { return curr && curr->contains(entt); });
- }
- public:
- using difference_type = typename underlying_iterator::difference_type;
- using value_type = typename underlying_iterator::value_type;
- using pointer = typename underlying_iterator::pointer;
- using reference = typename underlying_iterator::reference;
- using iterator_category = std::bidirectional_iterator_tag;
- view_iterator() ENTT_NOEXCEPT = default;
- view_iterator(const std::vector<const basic_common_type *> &cpools, const std::vector<const basic_common_type *> &ignore, underlying_iterator curr) ENTT_NOEXCEPT
- : pools{&cpools},
- filter{&ignore},
- it{curr},
- stable_storage{std::any_of(pools->cbegin(), pools->cend(), [](const basic_common_type *cpool) { return (cpool->policy() == deletion_policy::in_place); })}
- {
- if(it != (*pools)[0]->end() && !valid()) {
- ++(*this);
- }
- }
- view_iterator & operator++() {
- while(++it != (*pools)[0]->end() && !valid());
- return *this;
- }
- view_iterator operator++(int) {
- view_iterator orig = *this;
- return ++(*this), orig;
- }
- view_iterator & operator--() ENTT_NOEXCEPT {
- while(--it != (*pools)[0]->begin() && !valid());
- return *this;
- }
- view_iterator operator--(int) ENTT_NOEXCEPT {
- view_iterator orig = *this;
- return operator--(), orig;
- }
- [[nodiscard]] bool operator==(const view_iterator &other) const ENTT_NOEXCEPT {
- return other.it == it;
- }
- [[nodiscard]] bool operator!=(const view_iterator &other) const ENTT_NOEXCEPT {
- return !(*this == other);
- }
- [[nodiscard]] pointer operator->() const {
- return it.operator->();
- }
- [[nodiscard]] reference operator*() const {
- return *operator->();
- }
- private:
- const std::vector<const basic_common_type *> *pools;
- const std::vector<const basic_common_type *> *filter;
- underlying_iterator it;
- bool stable_storage;
- };
- [[nodiscard]] bool valid() const {
- return !pools.empty() && pools.front();
- }
- public:
- /*! @brief Underlying entity identifier. */
- using entity_type = Entity;
- /*! @brief Unsigned integer type. */
- using size_type = std::size_t;
- /*! @brief Bidirectional iterator type. */
- using iterator = view_iterator;
- /*! @brief Default constructor to use to create empty, invalid views. */
- basic_runtime_view() ENTT_NOEXCEPT
- : pools{},
- filter{}
- {}
- /**
- * @brief Constructs a runtime view from a set of storage classes.
- * @param cpools The storage for the types to iterate.
- * @param epools The storage for the types used to filter the view.
- */
- basic_runtime_view(std::vector<const basic_common_type *> cpools, std::vector<const basic_common_type *> epools) ENTT_NOEXCEPT
- : pools{std::move(cpools)},
- filter{std::move(epools)}
- {
- // brings the best candidate (if any) on front of the vector
- std::rotate(pools.begin(), std::min_element(pools.begin(), pools.end(), [](const auto *lhs, const auto *rhs) {
- return (!lhs && rhs) || (lhs && rhs && lhs->size() < rhs->size());
- }), pools.end());
- }
- /**
- * @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 valid() ? pools.front()->size() : size_type{};
- }
- /**
- * @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 valid() ? iterator{pools, filter, pools[0]->begin()} : iterator{};
- }
- /**
- * @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 valid() ? iterator{pools, filter, pools[0]->end()} : iterator{};
- }
- /**
- * @brief Checks if a view contains an entity.
- * @param entt A valid entity identifier.
- * @return True if the view contains the given entity, false otherwise.
- */
- [[nodiscard]] bool contains(const entity_type entt) const {
- return valid() && 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 basic_common_type *> pools;
- std::vector<const basic_common_type *> filter;
- };
- }
- #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 <unordered_map>
- #include <utility>
- #include <vector>
- // #include "../config/config.h"
- // #include "../core/type_traits.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 traits_type = 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 traits_type::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] : size[Index]), ...);
- }
- (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 &&) = default;
- /*! @brief Default move assignment operator. @return This snapshot. */
- basic_snapshot & operator=(basic_snapshot &&) = 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 traits_type::entity_type(sz));
- for(auto first = reg->data(), last = first + sz; first != last; ++first) {
- archive(*first);
- }
- archive(reg->released());
- 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.data(), view.data() + view.size()), ...);
- 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 traits_type = entt_traits<Entity>;
- template<typename Type, typename Archive>
- void assign(Archive &archive) const {
- typename traits_type::entity_type length{};
- archive(length);
- entity_type entt{};
- if constexpr(std::tuple_size_v<decltype(reg->template view<Type>().get({}))> == 0) {
- 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>(entity);
- }
- } 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>(entity, 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 &&) = default;
- /*! @brief Default move assignment operator. @return This loader. */
- basic_snapshot_loader & operator=(basic_snapshot_loader &&) = 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 traits_type::entity_type length{};
- archive(length);
- std::vector<entity_type> all(length);
- for(decltype(length) pos{}; pos < length; ++pos) {
- archive(all[pos]);
- }
- entity_type destroyed;
- archive(destroyed);
- reg->assign(all.cbegin(), all.cend(), destroyed);
- 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->orphans([this](const auto 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 traits_type = 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));
- }
- }
- std::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 traits_type::entity_type length{};
- archive(length);
- entity_type entt{};
- if constexpr(std::tuple_size_v<decltype(reg->template view<Other>().get({}))> == 0) {
- 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 traits_type::entity_type length{};
- entity_type entt{};
- archive(length);
- for(decltype(length) pos{}; pos < length; ++pos) {
- archive(entt);
- if(const auto entity = traits_type::to_entity(entt); entity == pos) {
- restore(entt);
- } else {
- destroy(entt);
- }
- }
- // discards the head of the list of destroyed entities
- archive(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->orphans([this](const auto entt) {
- reg->release(entt);
- });
- return *this;
- }
- /**
- * @brief Tests if a loader knows about a given entity.
- * @param entt An entity 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 An entity 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:
- std::unordered_map<entity_type, std::pair<entity_type, bool>> remloc;
- basic_registry<entity_type> *reg;
- };
- }
- #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 "../config/config.h"
- // #include "../core/algorithm.hpp"
- // #include "../core/fwd.hpp"
- // #include "entity.hpp"
- // #include "fwd.hpp"
- namespace entt {
- /*! @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 {
- static constexpr auto growth_factor = 1.5;
- static constexpr auto sparse_page = ENTT_SPARSE_PAGE;
- using traits_type = entt_traits<Entity>;
- using alloc_traits = typename std::allocator_traits<Allocator>::template rebind_traits<Entity>;
- using alloc_pointer = typename alloc_traits::pointer;
- using alloc_const_pointer = typename alloc_traits::const_pointer;
- using bucket_alloc_traits = typename std::allocator_traits<Allocator>::template rebind_traits<alloc_pointer>;
- using bucket_alloc_pointer = typename bucket_alloc_traits::pointer;
- static_assert(alloc_traits::propagate_on_container_move_assignment::value);
- static_assert(bucket_alloc_traits::propagate_on_container_move_assignment::value);
- struct sparse_set_iterator final {
- using difference_type = typename traits_type::difference_type;
- using value_type = Entity;
- using pointer = const value_type *;
- using reference = const value_type &;
- using iterator_category = std::random_access_iterator_tag;
- sparse_set_iterator() ENTT_NOEXCEPT = default;
- sparse_set_iterator(const alloc_const_pointer *ref, const difference_type idx) ENTT_NOEXCEPT
- : packed{ref},
- index{idx}
- {}
- sparse_set_iterator & operator++() ENTT_NOEXCEPT {
- return --index, *this;
- }
- sparse_set_iterator operator++(int) ENTT_NOEXCEPT {
- iterator orig = *this;
- return ++(*this), orig;
- }
- sparse_set_iterator & operator--() ENTT_NOEXCEPT {
- return ++index, *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 {
- index -= 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);
- }
- difference_type operator-(const sparse_set_iterator &other) const ENTT_NOEXCEPT {
- return other.index - index;
- }
- [[nodiscard]] reference operator[](const difference_type value) const {
- const auto pos = size_type(index-value-1u);
- return (*packed)[pos];
- }
- [[nodiscard]] bool operator==(const sparse_set_iterator &other) const ENTT_NOEXCEPT {
- return other.index == index;
- }
- [[nodiscard]] bool operator!=(const sparse_set_iterator &other) const ENTT_NOEXCEPT {
- return !(*this == other);
- }
- [[nodiscard]] bool operator<(const sparse_set_iterator &other) const ENTT_NOEXCEPT {
- return index > other.index;
- }
- [[nodiscard]] bool operator>(const sparse_set_iterator &other) const ENTT_NOEXCEPT {
- return index < other.index;
- }
- [[nodiscard]] bool operator<=(const sparse_set_iterator &other) const ENTT_NOEXCEPT {
- return !(*this > other);
- }
- [[nodiscard]] bool operator>=(const sparse_set_iterator &other) const ENTT_NOEXCEPT {
- return !(*this < other);
- }
- [[nodiscard]] pointer operator->() const {
- const auto pos = size_type(index-1u);
- return std::addressof((*packed)[pos]);
- }
- [[nodiscard]] reference operator*() const {
- return *operator->();
- }
- private:
- const alloc_const_pointer *packed;
- difference_type index;
- };
- [[nodiscard]] static auto page(const Entity entt) ENTT_NOEXCEPT {
- return size_type{traits_type::to_entity(entt) / sparse_page};
- }
- [[nodiscard]] static auto offset(const Entity entt) ENTT_NOEXCEPT {
- return size_type{traits_type::to_entity(entt) & (sparse_page - 1)};
- }
- [[nodiscard]] auto assure_page(const std::size_t idx) {
- if(!(idx < bucket)) {
- const size_type sz = idx + 1u;
- const auto mem = bucket_alloc_traits::allocate(bucket_allocator, sz);
- std::uninitialized_value_construct(mem + bucket, mem + sz);
- std::uninitialized_copy(sparse, sparse + bucket, mem);
- std::destroy(sparse, sparse + bucket);
- bucket_alloc_traits::deallocate(bucket_allocator, sparse, bucket);
- sparse = mem;
- bucket = sz;
- }
- if(!sparse[idx]) {
- sparse[idx] = alloc_traits::allocate(allocator, sparse_page);
- std::uninitialized_fill(sparse[idx], sparse[idx] + sparse_page, null);
- }
- return sparse[idx];
- }
- void resize_packed(const std::size_t req) {
- ENTT_ASSERT((req != reserved) && !(req < count), "Invalid request");
- const auto mem = alloc_traits::allocate(allocator, req);
- std::uninitialized_copy(packed, packed + count, mem);
- std::uninitialized_fill(mem + count, mem + req, tombstone);
- std::destroy(packed, packed + reserved);
- alloc_traits::deallocate(allocator, packed, reserved);
- packed = mem;
- reserved = req;
- }
- void release_memory() {
- if(packed) {
- for(size_type pos{}; pos < bucket; ++pos) {
- if(sparse[pos]) {
- std::destroy(sparse[pos], sparse[pos] + sparse_page);
- alloc_traits::deallocate(allocator, sparse[pos], sparse_page);
- }
- }
- std::destroy(packed, packed + reserved);
- std::destroy(sparse, sparse + bucket);
- alloc_traits::deallocate(allocator, packed, reserved);
- bucket_alloc_traits::deallocate(bucket_allocator, sparse, bucket);
- }
- }
- protected:
- /**
- * @brief Swaps two entities in the internal packed array.
- * @param lhs A valid position of an entity within storage.
- * @param rhs A valid position of an entity within storage.
- */
- virtual void swap_at([[maybe_unused]] const std::size_t lhs, [[maybe_unused]] const std::size_t rhs) {}
- /**
- * @brief Moves an entity in the internal packed array.
- * @param from A valid position of an entity within storage.
- * @param to A valid position of an entity within storage.
- */
- virtual void move_and_pop([[maybe_unused]] const std::size_t from, [[maybe_unused]] const std::size_t to) {}
- /**
- * @brief Attempts to erase an entity from the internal packed array.
- * @param entt A valid entity identifier.
- * @param ud Optional user data that are forwarded as-is to derived classes.
- */
- virtual void swap_and_pop(const Entity entt, [[maybe_unused]] void *ud) {
- auto &ref = sparse[page(entt)][offset(entt)];
- const auto pos = size_type{traits_type::to_entity(ref)};
- ENTT_ASSERT(packed[pos] == entt, "Invalid entity identifier");
- auto &last = packed[--count];
- packed[pos] = last;
- sparse[page(last)][offset(last)] = ref;
- // lazy self-assignment guard
- ref = null;
- // unnecessary but it helps to detect nasty bugs
- ENTT_ASSERT((last = tombstone, true), "");
- }
- /**
- * @brief Attempts to erase an entity from the internal packed array.
- * @param entt A valid entity identifier.
- * @param ud Optional user data that are forwarded as-is to derived classes.
- */
- virtual void in_place_pop(const Entity entt, [[maybe_unused]] void *ud) {
- auto &ref = sparse[page(entt)][offset(entt)];
- const auto pos = size_type{traits_type::to_entity(ref)};
- ENTT_ASSERT(packed[pos] == entt, "Invalid entity identifier");
- packed[pos] = std::exchange(free_list, traits_type::construct(static_cast<typename traits_type::entity_type>(pos)));
- // lazy self-assignment guard
- ref = null;
- }
- public:
- /*! @brief Allocator type. */
- using allocator_type = typename alloc_traits::allocator_type;
- /*! @brief Underlying entity identifier. */
- using entity_type = Entity;
- /*! @brief Unsigned integer type. */
- using size_type = std::size_t;
- /*! @brief Pointer type to contained entities. */
- using pointer = alloc_const_pointer;
- /*! @brief Random access iterator type. */
- using iterator = sparse_set_iterator;
- /*! @brief Reverse iterator type. */
- using reverse_iterator = std::reverse_iterator<iterator>;
- /**
- * @brief Constructs an empty container with the given policy and allocator.
- * @param pol Type of deletion policy.
- * @param alloc Allocator to use (possibly default-constructed).
- */
- explicit basic_sparse_set(deletion_policy pol, const allocator_type &alloc = {})
- : allocator{alloc},
- bucket_allocator{alloc},
- sparse{bucket_alloc_traits::allocate(bucket_allocator, 0u)},
- packed{alloc_traits::allocate(allocator, 0u)},
- bucket{0u},
- count{0u},
- reserved{0u},
- free_list{tombstone},
- mode{pol}
- {}
- /**
- * @brief Constructs an empty container with the given allocator.
- * @param alloc Allocator to use (possibly default-constructed).
- */
- explicit basic_sparse_set(const allocator_type &alloc = {})
- : basic_sparse_set{deletion_policy::swap_and_pop, alloc}
- {}
- /**
- * @brief Move constructor.
- * @param other The instance to move from.
- */
- basic_sparse_set(basic_sparse_set &&other) ENTT_NOEXCEPT
- : allocator{std::move(other.allocator)},
- bucket_allocator{std::move(other.bucket_allocator)},
- sparse{std::exchange(other.sparse, bucket_alloc_pointer{})},
- packed{std::exchange(other.packed, alloc_pointer{})},
- bucket{std::exchange(other.bucket, 0u)},
- count{std::exchange(other.count, 0u)},
- reserved{std::exchange(other.reserved, 0u)},
- free_list{std::exchange(other.free_list, tombstone)},
- mode{other.mode}
- {}
- /*! @brief Default destructor. */
- virtual ~basic_sparse_set() {
- release_memory();
- }
- /**
- * @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 {
- release_memory();
- allocator = std::move(other.allocator);
- bucket_allocator = std::move(other.bucket_allocator);
- sparse = std::exchange(other.sparse, bucket_alloc_pointer{});
- packed = std::exchange(other.packed, alloc_pointer{});
- bucket = std::exchange(other.bucket, 0u);
- count = std::exchange(other.count, 0u);
- reserved = std::exchange(other.reserved, 0u);
- free_list = std::exchange(other.free_list, tombstone);
- mode = other.mode;
- return *this;
- }
- /**
- * @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 Returns the next slot available for insertion.
- * @return The next slot available for insertion.
- */
- [[nodiscard]] size_type slot() const ENTT_NOEXCEPT {
- return free_list == null ? count : size_type{traits_type::to_entity(free_list)};
- }
- /**
- * @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.
- */
- void reserve(const size_type cap) {
- if(cap > reserved) {
- resize_packed(cap);
- }
- }
- /**
- * @brief Returns the number of elements that a sparse set has currently
- * allocated space for.
- * @return Capacity of the sparse set.
- */
- [[nodiscard]] size_type capacity() const ENTT_NOEXCEPT {
- return reserved;
- }
- /*! @brief Requests the removal of unused capacity. */
- void shrink_to_fit() {
- if(count < reserved) {
- resize_packed(count);
- }
- }
- /**
- * @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 bucket * sparse_page;
- }
- /**
- * @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 count;
- }
- /**
- * @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 (count == size_type{});
- }
- /**
- * @brief Direct access to the internal packed array.
- * @return A pointer to the internal packed array.
- */
- [[nodiscard]] pointer data() const ENTT_NOEXCEPT {
- return packed;
- }
- /**
- * @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 internal packed array.
- */
- [[nodiscard]] iterator begin() const ENTT_NOEXCEPT {
- return iterator{std::addressof(packed), static_cast<typename traits_type::difference_type>(count)};
- }
- /**
- * @brief Returns an iterator to the end.
- *
- * The returned iterator points to the element following the last entity in
- * the internal packed array. Attempting to dereference the returned
- * iterator results in undefined behavior.
- *
- * @return An iterator to the element following the last entity of the
- * internal packed array.
- */
- [[nodiscard]] iterator end() const ENTT_NOEXCEPT {
- return iterator{std::addressof(packed), {}};
- }
- /**
- * @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]] reverse_iterator rbegin() const 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 entity in
- * the reversed internal packed array. Attempting to dereference the
- * returned iterator results in undefined behavior.
- *
- * @return An iterator to the element following the last entity of the
- * reversed internal packed array.
- */
- [[nodiscard]] reverse_iterator rend() const ENTT_NOEXCEPT {
- return std::make_reverse_iterator(begin());
- }
- /**
- * @brief Finds an entity.
- * @param entt A valid entity 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 entity identifier.
- * @return True if the sparse set contains the entity, false otherwise.
- */
- [[nodiscard]] bool contains(const entity_type entt) const ENTT_NOEXCEPT {
- ENTT_ASSERT(entt != tombstone && entt != null, "Invalid entity");
- const auto curr = page(entt);
- // testing versions permits to avoid accessing the packed array
- return (curr < bucket && sparse[curr] && sparse[curr][offset(entt)] != null);
- }
- /**
- * @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 entity 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 size_type{traits_type::to_entity(sparse[page(entt)][offset(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 < count ? 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 < count, "Position is out of bounds");
- return packed[pos];
- }
- /**
- * @brief Appends 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 entity identifier.
- * @return The slot used for insertion.
- */
- size_type emplace_back(const entity_type entt) {
- ENTT_ASSERT(!contains(entt), "Set already contains entity");
- if(count == reserved) {
- const size_type sz = static_cast<size_type>(reserved * growth_factor);
- resize_packed(sz + !(sz > reserved));
- }
- assure_page(page(entt))[offset(entt)] = traits_type::construct(static_cast<typename traits_type::entity_type>(count));
- packed[count] = entt;
- return count++;
- }
- /**
- * @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 entity identifier.
- * @return The slot used for insertion.
- */
- size_type emplace(const entity_type entt) {
- if(free_list == null) {
- return emplace_back(entt);
- } else {
- ENTT_ASSERT(!contains(entt), "Set already contains entity");
- const auto pos = size_type{traits_type::to_entity(free_list)};
- sparse[page(entt)][offset(entt)] = traits_type::construct(static_cast<typename traits_type::entity_type>(pos));
- free_list = std::exchange(packed[pos], entt);
- return pos;
- }
- }
- /**
- * @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.
- */
- template<typename It>
- void insert(It first, It last) {
- reserve(count + std::distance(first, last));
- for(; first != last; ++first) {
- const auto entt = *first;
- ENTT_ASSERT(!contains(entt), "Set already contains entity");
- assure_page(page(entt))[offset(entt)] = traits_type::construct(static_cast<typename traits_type::entity_type>(count));
- packed[count++] = entt;
- }
- }
- /**
- * @brief Erases an entity from a sparse set.
- *
- * @warning
- * Attempting to erase an entity that doesn't belong to the sparse set
- * results in undefined behavior.
- *
- * @param entt A valid entity identifier.
- * @param ud Optional user data that are forwarded as-is to derived classes.
- */
- void erase(const entity_type entt, void *ud = nullptr) {
- ENTT_ASSERT(contains(entt), "Set does not contain entity");
- (mode == deletion_policy::in_place) ? in_place_pop(entt, ud) : swap_and_pop(entt, ud);
- }
- /**
- * @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.
- * @param ud Optional user data that are forwarded as-is to derived classes.
- */
- template<typename It>
- void erase(It first, It last, void *ud = nullptr) {
- for(; first != last; ++first) {
- erase(*first, ud);
- }
- }
- /**
- * @brief Removes an entity from a sparse set if it exists.
- * @param entt A valid entity identifier.
- * @param ud Optional user data that are forwarded as-is to derived classes.
- * @return True if the entity is actually removed, false otherwise.
- */
- bool remove(const entity_type entt, void *ud = nullptr) {
- return contains(entt) && (erase(entt, ud), 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.
- * @param ud Optional user data that are forwarded as-is to derived classes.
- * @return The number of entities actually removed.
- */
- template<typename It>
- size_type remove(It first, It last, void *ud = nullptr) {
- size_type found{};
- for(; first != last; ++first) {
- found += remove(*first, ud);
- }
- return found;
- }
- /*! @brief Removes all tombstones from the packed array of a sparse set. */
- void compact() {
- size_type next = count;
- for(; next && packed[next - 1u] == tombstone; --next);
- for(auto *it = &free_list; *it != null && next; it = std::addressof(packed[traits_type::to_entity(*it)])) {
- if(const size_type pos = traits_type::to_entity(*it); pos < next) {
- --next;
- move_and_pop(next, pos);
- std::swap(packed[next], packed[pos]);
- sparse[page(packed[pos])][offset(packed[pos])] = traits_type::construct(static_cast<const typename traits_type::entity_type>(pos));
- *it = traits_type::construct(static_cast<typename traits_type::entity_type>(next));
- for(; next && packed[next - 1u] == tombstone; --next);
- }
- }
- free_list = tombstone;
- count = next;
- }
- /**
- * @copybrief swap_at
- *
- * 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 entity identifier.
- * @param rhs A valid entity identifier.
- */
- void swap(const entity_type lhs, const entity_type rhs) {
- ENTT_ASSERT(contains(lhs), "Set does not contain entity");
- ENTT_ASSERT(contains(rhs), "Set does not contain entity");
- auto &entt = sparse[page(lhs)][offset(lhs)];
- auto &other = sparse[page(rhs)][offset(rhs)];
- const auto from = size_type{traits_type::to_entity(entt)};
- const auto to = size_type{traits_type::to_entity(other)};
- // basic no-leak guarantee (with invalid state) if swapping throws
- swap_at(from, to);
- std::swap(entt, other);
- std::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) {
- // basic no-leak guarantee (with invalid state) if sorting throws
- ENTT_ASSERT(!(length > count), "Length exceeds the number of elements");
- compact();
- algo(std::make_reverse_iterator(packed + length), std::make_reverse_iterator(packed), 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);
- sparse[page(entt)][offset(entt)] = traits_type::construct(static_cast<typename traits_type::entity_type>(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) {
- sort_n(count, 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 = count - 1; pos && from != to; ++from) {
- if(contains(*from)) {
- if(*from != packed[pos]) {
- // basic no-leak guarantee (with invalid state) if swapping throws
- swap(packed[pos], *from);
- }
- --pos;
- }
- }
- }
- /**
- * @brief Clears a sparse set.
- * @param ud Optional user data that are forwarded as-is to derived classes.
- */
- void clear(void *ud = nullptr) {
- for(auto &&entity: *this) {
- if(entity != tombstone) {
- in_place_pop(entity, ud);
- }
- }
- free_list = tombstone;
- count = 0u;
- }
- private:
- typename alloc_traits::allocator_type allocator;
- typename bucket_alloc_traits::allocator_type bucket_allocator;
- bucket_alloc_pointer sparse;
- alloc_pointer packed;
- std::size_t bucket;
- std::size_t count;
- std::size_t reserved;
- entity_type free_list;
- deletion_policy mode;
- };
- }
- #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 "../config/config.h"
- // #include "../core/algorithm.hpp"
- // #include "../core/fwd.hpp"
- // #include "../core/type_traits.hpp"
- // #include "../signal/sigh.hpp"
- // #include "component.hpp"
- // #include "entity.hpp"
- // #include "fwd.hpp"
- // #include "sparse_set.hpp"
- namespace entt {
- /**
- * @brief Basic storage implementation.
- *
- * This class is a refinement of a sparse set that associates an object to an
- * entity. The main purpose of this class is to extend sparse sets to store
- * components in a registry. It guarantees fast access both to the elements and
- * to the entities.
- *
- * @note
- * Entities and objects have the same order.
- *
- * @note
- * 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.
- *
- * @sa sparse_set<Entity>
- *
- * @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 = void>
- class basic_storage_impl: public basic_sparse_set<Entity, typename std::allocator_traits<Allocator>::template rebind_alloc<Entity>> {
- static constexpr auto packed_page = ENTT_PACKED_PAGE;
- using comp_traits = component_traits<Type>;
- using underlying_type = basic_sparse_set<Entity, typename std::allocator_traits<Allocator>::template rebind_alloc<Entity>>;
- using difference_type = typename entt_traits<Entity>::difference_type;
- using alloc_traits = typename std::allocator_traits<Allocator>::template rebind_traits<Type>;
- using alloc_pointer = typename alloc_traits::pointer;
- using alloc_const_pointer = typename alloc_traits::const_pointer;
- using bucket_alloc_traits = typename std::allocator_traits<Allocator>::template rebind_traits<alloc_pointer>;
- using bucket_alloc_pointer = typename bucket_alloc_traits::pointer;
- using bucket_alloc_const_type = typename std::allocator_traits<Allocator>::template rebind_alloc<alloc_const_pointer>;
- using bucket_alloc_const_pointer = typename std::allocator_traits<bucket_alloc_const_type>::const_pointer;
- static_assert(alloc_traits::propagate_on_container_move_assignment::value);
- static_assert(bucket_alloc_traits::propagate_on_container_move_assignment::value);
- template<typename Value>
- struct storage_iterator final {
- using difference_type = typename basic_storage_impl::difference_type;
- using value_type = Value;
- using pointer = value_type *;
- using reference = value_type &;
- using iterator_category = std::random_access_iterator_tag;
- storage_iterator() ENTT_NOEXCEPT = default;
- storage_iterator(bucket_alloc_pointer const *ref, const typename basic_storage_impl::difference_type idx) ENTT_NOEXCEPT
- : packed{ref},
- index{idx}
- {}
- storage_iterator & operator++() ENTT_NOEXCEPT {
- return --index, *this;
- }
- storage_iterator operator++(int) ENTT_NOEXCEPT {
- storage_iterator orig = *this;
- return ++(*this), orig;
- }
- storage_iterator & operator--() ENTT_NOEXCEPT {
- return ++index, *this;
- }
- storage_iterator operator--(int) ENTT_NOEXCEPT {
- storage_iterator orig = *this;
- return operator--(), orig;
- }
- storage_iterator & operator+=(const difference_type value) ENTT_NOEXCEPT {
- index -= 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);
- }
- difference_type operator-(const storage_iterator &other) const ENTT_NOEXCEPT {
- return other.index - index;
- }
- [[nodiscard]] reference operator[](const difference_type value) const ENTT_NOEXCEPT {
- const auto pos = size_type(index-value-1);
- return (*packed)[page(pos)][offset(pos)];
- }
- [[nodiscard]] bool operator==(const storage_iterator &other) const ENTT_NOEXCEPT {
- return other.index == index;
- }
- [[nodiscard]] bool operator!=(const storage_iterator &other) const ENTT_NOEXCEPT {
- return !(*this == other);
- }
- [[nodiscard]] bool operator<(const storage_iterator &other) const ENTT_NOEXCEPT {
- return index > other.index;
- }
- [[nodiscard]] bool operator>(const storage_iterator &other) const ENTT_NOEXCEPT {
- return index < other.index;
- }
- [[nodiscard]] bool operator<=(const storage_iterator &other) const ENTT_NOEXCEPT {
- return !(*this > other);
- }
- [[nodiscard]] bool operator>=(const storage_iterator &other) const ENTT_NOEXCEPT {
- return !(*this < other);
- }
- [[nodiscard]] pointer operator->() const ENTT_NOEXCEPT {
- const auto pos = size_type(index-1u);
- return std::addressof((*packed)[page(pos)][offset(pos)]);
- }
- [[nodiscard]] reference operator*() const ENTT_NOEXCEPT {
- return *operator->();
- }
- private:
- bucket_alloc_pointer const *packed;
- difference_type index;
- };
- [[nodiscard]] static auto page(const std::size_t pos) ENTT_NOEXCEPT {
- return pos / packed_page;
- }
- [[nodiscard]] static auto offset(const std::size_t pos) ENTT_NOEXCEPT {
- return pos & (packed_page - 1);
- }
- void release_memory() {
- if(packed) {
- // no-throw stable erase iteration
- underlying_type::clear();
- for(size_type pos{}; pos < bucket; ++pos) {
- alloc_traits::deallocate(allocator, packed[pos], packed_page);
- bucket_alloc_traits::destroy(bucket_allocator, std::addressof(packed[pos]));
- }
- bucket_alloc_traits::deallocate(bucket_allocator, packed, bucket);
- }
- }
- void assure_at_least(const std::size_t last) {
- if(const auto idx = page(last - 1u); !(idx < bucket)) {
- const size_type sz = idx + 1u;
- const auto mem = bucket_alloc_traits::allocate(bucket_allocator, sz);
- std::uninitialized_copy(packed, packed + bucket, mem);
- size_type pos{};
- ENTT_TRY {
- for(pos = bucket; pos < sz; ++pos) {
- auto pg = alloc_traits::allocate(allocator, packed_page);
- bucket_alloc_traits::construct(bucket_allocator, std::addressof(mem[pos]), pg);
- }
- } ENTT_CATCH {
- for(auto next = bucket; next < pos; ++next) {
- alloc_traits::deallocate(allocator, mem[next], packed_page);
- }
- std::destroy(mem, mem + pos);
- bucket_alloc_traits::deallocate(bucket_allocator, mem, sz);
- ENTT_THROW;
- }
- std::destroy(packed, packed + bucket);
- bucket_alloc_traits::deallocate(bucket_allocator, packed, bucket);
- packed = mem;
- bucket = sz;
- }
- }
- void release_unused_pages() {
- if(const auto length = underlying_type::size() / packed_page; length < bucket) {
- const auto mem = bucket_alloc_traits::allocate(bucket_allocator, length);
- std::uninitialized_copy(packed, packed + length, mem);
- for(auto pos = length; pos < bucket; ++pos) {
- alloc_traits::deallocate(allocator, packed[pos], packed_page);
- bucket_alloc_traits::destroy(bucket_allocator, std::addressof(packed[pos]));
- }
- bucket_alloc_traits::deallocate(bucket_allocator, packed, bucket);
- packed = mem;
- bucket = length;
- }
- }
- template<typename... Args>
- auto & push_at(const std::size_t pos, Args &&... args) {
- ENTT_ASSERT(pos < (bucket * packed_page), "Out of bounds index");
- auto *instance = std::addressof(packed[page(pos)][offset(pos)]);
- if constexpr(std::is_aggregate_v<value_type>) {
- alloc_traits::construct(allocator, instance, Type{std::forward<Args>(args)...});
- } else {
- alloc_traits::construct(allocator, instance, std::forward<Args>(args)...);
- }
- return *instance;
- }
- void pop_at(const std::size_t pos) {
- alloc_traits::destroy(allocator, std::addressof(packed[page(pos)][offset(pos)]));
- }
- protected:
- /*! @copydoc basic_sparse_set::swap_at */
- void swap_at(const std::size_t lhs, const std::size_t rhs) final {
- std::swap(packed[page(lhs)][offset(lhs)], packed[page(rhs)][offset(rhs)]);
- }
- /*! @copydoc basic_sparse_set::move_and_pop */
- void move_and_pop(const std::size_t from, const std::size_t to) final {
- push_at(to, std::move(packed[page(from)][offset(from)]));
- pop_at(from);
- }
- /*! @copydoc basic_sparse_set::swap_and_pop */
- void swap_and_pop(const Entity entt, void *ud) override {
- const auto pos = underlying_type::index(entt);
- const auto last = underlying_type::size() - 1u;
- auto &&elem = packed[page(pos)][offset(pos)];
- // support for nosy destructors
- [[maybe_unused]] auto unused = std::move(elem);
- elem = std::move(packed[page(last)][offset(last)]);
- pop_at(last);
- underlying_type::swap_and_pop(entt, ud);
- }
- /*! @copydoc basic_sparse_set::in_place_pop */
- void in_place_pop(const Entity entt, void *ud) override {
- const auto pos = underlying_type::index(entt);
- underlying_type::in_place_pop(entt, ud);
- // support for nosy destructors
- pop_at(pos);
- }
- public:
- /*! @brief Allocator type. */
- using allocator_type = typename alloc_traits::allocator_type;
- /*! @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 = bucket_alloc_pointer;
- /*! @brief Constant pointer type to contained elements. */
- using const_pointer = bucket_alloc_const_pointer;
- /*! @brief Random access iterator type. */
- using iterator = storage_iterator<value_type>;
- /*! @brief Constant random access iterator type. */
- using const_iterator = storage_iterator<const value_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 Default constructor.
- * @param alloc Allocator to use (possibly default-constructed).
- */
- explicit basic_storage_impl(const allocator_type &alloc = {})
- : underlying_type{deletion_policy{comp_traits::in_place_delete::value}, alloc},
- allocator{alloc},
- bucket_allocator{alloc},
- packed{bucket_alloc_traits::allocate(bucket_allocator, 0u)},
- bucket{}
- {}
- /**
- * @brief Move constructor.
- * @param other The instance to move from.
- */
- basic_storage_impl(basic_storage_impl &&other) ENTT_NOEXCEPT
- : underlying_type{std::move(other)},
- allocator{std::move(other.allocator)},
- bucket_allocator{std::move(other.bucket_allocator)},
- packed{std::exchange(other.packed, bucket_alloc_pointer{})},
- bucket{std::exchange(other.bucket, 0u)}
- {}
- /*! @brief Default destructor. */
- ~basic_storage_impl() override {
- release_memory();
- }
- /**
- * @brief Move assignment operator.
- * @param other The instance to move from.
- * @return This sparse set.
- */
- basic_storage_impl & operator=(basic_storage_impl &&other) ENTT_NOEXCEPT {
- release_memory();
- underlying_type::operator=(std::move(other));
- allocator = std::move(other.allocator);
- bucket_allocator = std::move(other.bucket_allocator);
- packed = std::exchange(other.packed, bucket_alloc_pointer{});
- bucket = std::exchange(other.bucket, 0u);
- return *this;
- }
- /**
- * @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) {
- underlying_type::reserve(cap);
- if(cap > underlying_type::size()) {
- assure_at_least(cap);
- }
- }
- /**
- * @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 {
- return bucket * packed_page;
- }
- /*! @brief Requests the removal of unused capacity. */
- void shrink_to_fit() {
- underlying_type::shrink_to_fit();
- release_unused_pages();
- }
- /**
- * @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;
- }
- /*! @copydoc raw */
- [[nodiscard]] pointer raw() ENTT_NOEXCEPT {
- return packed;
- }
- /**
- * @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 difference_type pos = underlying_type::size();
- return const_iterator{std::addressof(packed), pos};
- }
- /*! @copydoc cbegin */
- [[nodiscard]] const_iterator begin() const ENTT_NOEXCEPT {
- return cbegin();
- }
- /*! @copydoc begin */
- [[nodiscard]] iterator begin() ENTT_NOEXCEPT {
- const difference_type pos = underlying_type::size();
- return iterator{std::addressof(packed), 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{std::addressof(packed), {}};
- }
- /*! @copydoc cend */
- [[nodiscard]] const_iterator end() const ENTT_NOEXCEPT {
- return cend();
- }
- /*! @copydoc end */
- [[nodiscard]] iterator end() ENTT_NOEXCEPT {
- return iterator{std::addressof(packed), {}};
- }
- /**
- * @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 entity identifier.
- * @return The object assigned to the entity.
- */
- [[nodiscard]] const value_type & get(const entity_type entt) const ENTT_NOEXCEPT {
- const auto idx = underlying_type::index(entt);
- return packed[page(idx)][offset(idx)];
- }
- /*! @copydoc get */
- [[nodiscard]] value_type & get(const entity_type entt) ENTT_NOEXCEPT {
- return const_cast<value_type &>(std::as_const(*this).get(entt));
- }
- /**
- * @brief Assigns an entity to a storage and constructs its object.
- *
- * This version accept both types that can be constructed in place directly
- * and types like aggregates that do not work well with a placement new as
- * performed usually under the hood during an _emplace back_.
- *
- * @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 entity 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) {
- const auto pos = underlying_type::slot();
- assure_at_least(pos + 1u);
- auto &value = push_at(pos, std::forward<Args>(args)...);
- ENTT_TRY {
- [[maybe_unused]] const auto curr = underlying_type::emplace(entt);
- ENTT_ASSERT(pos == curr, "Misplaced component");
- } ENTT_CATCH {
- pop_at(pos);
- ENTT_THROW;
- }
- return value;
- }
- /**
- * @brief Updates the instance assigned to a given entity in-place.
- * @tparam Func Types of the function objects to invoke.
- * @param entt A valid entity identifier.
- * @param func Valid function objects.
- * @return A reference to the updated instance.
- */
- template<typename... Func>
- decltype(auto) patch(const entity_type entt, Func &&... func) {
- const auto idx = underlying_type::index(entt);
- auto &&elem = packed[page(idx)][offset(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 = {}) {
- const auto cap = underlying_type::size() + std::distance(first, last);
- underlying_type::reserve(cap);
- assure_at_least(cap);
- for(; first != last; ++first) {
- push_at(underlying_type::size(), value);
- ENTT_TRY {
- underlying_type::emplace_back(*first);
- } ENTT_CATCH {
- pop_at(underlying_type::size());
- ENTT_THROW;
- }
- }
- }
- /**
- * @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<std::decay_t<typename std::iterator_traits<CIt>::value_type>, value_type>>>
- void insert(EIt first, EIt last, CIt from) {
- const auto cap = underlying_type::size() + std::distance(first, last);
- underlying_type::reserve(cap);
- assure_at_least(cap);
- for(; first != last; ++first, ++from) {
- push_at(underlying_type::size(), *from);
- ENTT_TRY {
- underlying_type::emplace_back(*first);
- } ENTT_CATCH {
- pop_at(underlying_type::size());
- ENTT_THROW;
- }
- }
- }
- /**
- * @brief Sort 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 one of the following:
- *
- * @code{.cpp}
- * bool(const Entity, const Entity);
- * bool(const Type &, const Type &);
- * @endcode
- *
- * Moreover, the comparison function object shall induce a
- * _strict weak ordering_ on the values.
- *
- * The sort function oject 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.
- *
- * @warning
- * Empty types are never instantiated. Therefore, only comparison function
- * objects that require to return entities rather than components are
- * accepted.
- *
- * @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) {
- if constexpr(std::is_invocable_v<Compare, const value_type &, const value_type &>) {
- underlying_type::sort_n(length, [this, compare = std::move(compare)](const auto lhs, const auto rhs) {
- const auto ilhs = underlying_type::index(lhs), irhs = underlying_type::index(rhs);
- return compare(std::as_const(packed[page(ilhs)][offset(ilhs)]), std::as_const(packed[page(irhs)][offset(irhs)]));
- }, std::move(algo), std::forward<Args>(args)...);
- } else {
- underlying_type::sort_n(length, std::move(compare), std::move(algo), std::forward<Args>(args)...);
- }
- }
- /**
- * @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) {
- sort_n(underlying_type::size(), std::move(compare), std::move(algo), std::forward<Args>(args)...);
- }
- private:
- typename alloc_traits::allocator_type allocator;
- typename bucket_alloc_traits::allocator_type bucket_allocator;
- bucket_alloc_pointer packed;
- size_type bucket;
- };
- /*! @copydoc basic_storage_impl */
- template<typename Entity, typename Type, typename Allocator>
- class basic_storage_impl<Entity, Type, Allocator, std::enable_if_t<component_traits<Type>::ignore_if_empty::value && std::is_empty_v<Type>>>
- : public basic_sparse_set<Entity, typename std::allocator_traits<Allocator>::template rebind_alloc<Entity>>
- {
- using comp_traits = component_traits<Type>;
- using underlying_type = basic_sparse_set<Entity, typename std::allocator_traits<Allocator>::template rebind_alloc<Entity>>;
- using alloc_traits = typename std::allocator_traits<Allocator>::template rebind_traits<Type>;
- public:
- /*! @brief Allocator type. */
- using allocator_type = typename alloc_traits::allocator_type;
- /*! @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 Default constructor.
- * @param alloc Allocator to use (possibly default-constructed).
- */
- explicit basic_storage_impl(const allocator_type &alloc = {})
- : underlying_type{deletion_policy{comp_traits::in_place_delete::value}, alloc}
- {}
- /**
- * @brief Fake get function.
- *
- * @warning
- * Attempting to use an entity that doesn't belong to the storage results in
- * undefined behavior.
- *
- * @param entt A valid entity identifier.
- */
- void get([[maybe_unused]] const entity_type entt) const ENTT_NOEXCEPT {
- ENTT_ASSERT(underlying_type::contains(entt), "Storage does not contain entity");
- }
- /**
- * @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 entity identifier.
- * @param args Parameters to use to construct an object for the entity.
- */
- template<typename... Args>
- void emplace(const entity_type entt, Args &&... args) {
- [[maybe_unused]] value_type instance{std::forward<Args>(args)...};
- underlying_type::emplace(entt);
- }
- /**
- * @brief Updates the instance assigned to a given entity in-place.
- * @tparam Func Types of the function objects to invoke.
- * @param entt A valid entity identifier.
- * @param func Valid function objects.
- */
- template<typename... Func>
- void patch([[maybe_unused]] const entity_type entt, Func &&... func) {
- ENTT_ASSERT(underlying_type::contains(entt), "Storage does not contain entity");
- (std::forward<Func>(func)(), ...);
- }
- /**
- * @brief Assigns one or more entities to a storage.
- *
- * @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.
- */
- template<typename It>
- void insert(It first, It last, const value_type & = {}) {
- underlying_type::insert(first, last);
- }
- };
- /**
- * @brief Mixin type to use to wrap basic storage classes.
- * @tparam Type The type of the underlying storage.
- */
- template<typename Type>
- struct storage_adapter_mixin: Type {
- static_assert(std::is_same_v<typename Type::value_type, std::decay_t<typename Type::value_type>>, "Invalid object type");
- /*! @brief Type of the objects assigned to entities. */
- using value_type = typename Type::value_type;
- /*! @brief Underlying entity identifier. */
- using entity_type = typename Type::entity_type;
- /*! @brief Inherited constructors. */
- using Type::Type;
- /**
- * @brief Assigns entities to a storage.
- * @tparam Args Types of arguments to use to construct the object.
- * @param entt A valid entity identifier.
- * @param args Parameters to use to initialize the object.
- * @return A reference to the newly created object.
- */
- template<typename... Args>
- decltype(auto) emplace(basic_registry<entity_type> &, const entity_type entt, Args &&... args) {
- return Type::emplace(entt, std::forward<Args>(args)...);
- }
- /**
- * @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(basic_registry<entity_type> &, It first, It last, Args &&... args) {
- Type::insert(first, last, std::forward<Args>(args)...);
- }
- /**
- * @brief Patches the given instance for an entity.
- * @tparam Func Types of the function objects to invoke.
- * @param entt A valid entity identifier.
- * @param func Valid function objects.
- * @return A reference to the patched instance.
- */
- template<typename... Func>
- decltype(auto) patch(basic_registry<entity_type> &, const entity_type entt, Func &&... func) {
- return Type::patch(entt, std::forward<Func>(func)...);
- }
- };
- /**
- * @brief Mixin type to use to add signal support to storage types.
- * @tparam Type The type of the underlying storage.
- */
- template<typename Type>
- class sigh_storage_mixin final: public Type {
- /*! @copydoc basic_sparse_set::swap_and_pop */
- void swap_and_pop(const typename Type::entity_type entt, void *ud) final {
- ENTT_ASSERT(ud != nullptr, "Invalid pointer to registry");
- destruction.publish(*static_cast<basic_registry<typename Type::entity_type> *>(ud), entt);
- Type::swap_and_pop(entt, ud);
- }
- /*! @copydoc basic_sparse_set::in_place_pop */
- void in_place_pop(const typename Type::entity_type entt, void *ud) final {
- ENTT_ASSERT(ud != nullptr, "Invalid pointer to registry");
- destruction.publish(*static_cast<basic_registry<typename Type::entity_type> *>(ud), entt);
- Type::in_place_pop(entt, ud);
- }
- public:
- /*! @brief Underlying value type. */
- using value_type = typename Type::value_type;
- /*! @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/>
- * The function type for a listener is equivalent to:
- *
- * @code{.cpp}
- * void(basic_registry<entity_type> &, entity_type);
- * @endcode
- *
- * 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/>
- * The function type for a listener is equivalent to:
- *
- * @code{.cpp}
- * void(basic_registry<entity_type> &, entity_type);
- * @endcode
- *
- * 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/>
- * The function type for a listener is equivalent to:
- *
- * @code{.cpp}
- * void(basic_registry<entity_type> &, entity_type);
- * @endcode
- *
- * 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 owner The registry that issued the request.
- * @param entt A valid entity identifier.
- * @param args Parameters to use to initialize the object.
- * @return A reference to the newly created object.
- */
- template<typename... Args>
- decltype(auto) emplace(basic_registry<entity_type> &owner, const entity_type entt, Args &&... args) {
- Type::emplace(entt, std::forward<Args>(args)...);
- construction.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 owner The registry that issued the request.
- * @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(basic_registry<entity_type> &owner, It first, It last, Args &&... args) {
- Type::insert(first, last, std::forward<Args>(args)...);
- if(!construction.empty()) {
- for(; first != last; ++first) {
- construction.publish(owner, *first);
- }
- }
- }
- /**
- * @brief Patches the given instance for an entity.
- * @tparam Func Types of the function objects to invoke.
- * @param owner The registry that issued the request.
- * @param entt A valid entity identifier.
- * @param func Valid function objects.
- * @return A reference to the patched instance.
- */
- template<typename... Func>
- decltype(auto) patch(basic_registry<entity_type> &owner, const entity_type entt, Func &&... func) {
- Type::patch(entt, std::forward<Func>(func)...);
- update.publish(owner, entt);
- return this->get(entt);
- }
- 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{};
- };
- /**
- * @brief Storage implementation dispatcher.
- * @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>
- struct basic_storage: basic_storage_impl<Entity, Type, Allocator> {
- using basic_storage_impl<Entity, Type, Allocator>::basic_storage_impl;
- };
- /**
- * @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>>;
- };
- /**
- * @brief Gets the element assigned to an entity from a storage, if any.
- * @tparam Type Storage type.
- * @param container A valid instance of a storage class.
- * @param entt A valid entity identifier.
- * @return A possibly empty tuple containing the requested element.
- */
- template<typename Type>
- [[nodiscard]] auto get_as_tuple([[maybe_unused]] Type &container, [[maybe_unused]] const typename Type::entity_type entt) {
- static_assert(std::is_same_v<std::remove_const_t<Type>, typename storage_traits<typename Type::entity_type, typename Type::value_type>::storage_type>, "Invalid storage");
- if constexpr(std::is_void_v<decltype(container.get({}))>) {
- return std::make_tuple();
- } else {
- return std::forward_as_tuple(container.get(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{};
- }
- #endif
- // #include "entity/view.hpp"
- #ifndef ENTT_ENTITY_VIEW_HPP
- #define ENTT_ENTITY_VIEW_HPP
- #include <iterator>
- #include <array>
- #include <tuple>
- #include <utility>
- #include <algorithm>
- #include <type_traits>
- // #include "../config/config.h"
- // #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 Policy, typename It, std::size_t AllOf, std::size_t NoneOf>
- class view_iterator final {
- using basic_common_type = basic_sparse_set<typename std::iterator_traits<It>::value_type>;
- [[nodiscard]] bool valid() const {
- const auto entt = *it;
- return Policy::accept(entt)
- && std::apply([entt](const auto *... curr) { return (curr->contains(entt) && ...); }, pools)
- && std::apply([entt](const auto *... curr) { return (!curr->contains(entt) && ...); }, filter);
- }
- public:
- using iterator_type = It;
- using difference_type = typename std::iterator_traits<It>::difference_type;
- using value_type = typename std::iterator_traits<It>::value_type;
- using pointer = typename std::iterator_traits<It>::pointer;
- using reference = typename std::iterator_traits<It>::reference;
- using iterator_category = std::bidirectional_iterator_tag;
- view_iterator() ENTT_NOEXCEPT
- : first{},
- last{},
- it{},
- pools{},
- filter{}
- {}
- view_iterator(It from, It to, It curr, std::array<const basic_common_type *, AllOf> all_of, std::array<const basic_common_type *, NoneOf> none_of) ENTT_NOEXCEPT
- : first{from},
- last{to},
- it{curr},
- 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;
- }
- view_iterator & operator--() ENTT_NOEXCEPT {
- while(--it != first && !valid());
- return *this;
- }
- view_iterator operator--(int) ENTT_NOEXCEPT {
- view_iterator orig = *this;
- return operator--(), orig;
- }
- [[nodiscard]] bool operator==(const view_iterator &other) const ENTT_NOEXCEPT {
- return other.it == it;
- }
- [[nodiscard]] bool operator!=(const view_iterator &other) const ENTT_NOEXCEPT {
- return !(*this == other);
- }
- [[nodiscard]] pointer operator->() const {
- return &*it;
- }
- [[nodiscard]] reference operator*() const {
- return *operator->();
- }
- private:
- It first;
- It last;
- It it;
- std::array<const basic_common_type *, AllOf> pools;
- std::array<const basic_common_type *, NoneOf> filter;
- };
- }
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /*! @brief Stable storage policy, aimed at pointer stability. */
- struct stable_storage_policy {
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- template<typename Entity>
- [[nodiscard]] static constexpr bool accept(const Entity entity) ENTT_NOEXCEPT {
- return entity != tombstone;
- }
- /**
- * Internal details not to be documented.
- * @endcond
- */
- };
- /*! @brief Packed storage policy, aimed at faster linear iteration. */
- struct packed_storage_policy {
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- template<typename Entity>
- [[nodiscard]] static constexpr bool accept(const Entity) ENTT_NOEXCEPT {
- return true;
- }
- /**
- * 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...>
- class basic_view_impl;
- /*! @brief View implementation dispatcher. */
- template<typename...>
- struct 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.
- *
- * @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 views.
- *
- * @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 Policy Common (stricter) storage policy.
- * @tparam Entity A valid entity type (see entt_traits for more details).
- * @tparam Exclude Types of components used to filter the view.
- * @tparam Component Types of components iterated by the view.
- */
- template<typename Policy, typename Entity, typename... Exclude, typename... Component>
- class basic_view_impl<Policy, Entity, exclude_t<Exclude...>, Component...> {
- using basic_common_type = basic_sparse_set<Entity>;
- template<typename Comp>
- using storage_type = constness_as_t<typename storage_traits<Entity, std::remove_const_t<Comp>>::storage_type, Comp>;
- class iterable final {
- template<typename It>
- struct iterable_iterator final {
- using difference_type = std::ptrdiff_t;
- using value_type = decltype(std::tuple_cat(std::tuple<Entity>{}, std::declval<basic_view_impl>().get({})));
- using pointer = void;
- using reference = value_type;
- using iterator_category = std::input_iterator_tag;
- iterable_iterator(It from, const basic_view_impl *parent) ENTT_NOEXCEPT
- : it{from},
- view{parent}
- {}
- iterable_iterator & operator++() ENTT_NOEXCEPT {
- return ++it, *this;
- }
- iterable_iterator operator++(int) ENTT_NOEXCEPT {
- iterable_iterator orig = *this;
- return ++(*this), orig;
- }
- [[nodiscard]] reference operator*() const ENTT_NOEXCEPT {
- return std::tuple_cat(std::make_tuple(*it), view->get(*it));
- }
- [[nodiscard]] bool operator==(const iterable_iterator &other) const ENTT_NOEXCEPT {
- return other.it == it;
- }
- [[nodiscard]] bool operator!=(const iterable_iterator &other) const ENTT_NOEXCEPT {
- return !(*this == other);
- }
- private:
- It it;
- const basic_view_impl *view;
- };
- public:
- using iterator = iterable_iterator<internal::view_iterator<Policy, typename basic_common_type::iterator, sizeof...(Component) - 1u, sizeof...(Exclude)>>;
- using reverse_iterator = iterable_iterator<internal::view_iterator<Policy, typename basic_common_type::reverse_iterator, sizeof...(Component) - 1u, sizeof...(Exclude)>>;
- iterable(const basic_view_impl &parent)
- : view{parent}
- {}
- [[nodiscard]] iterator begin() const ENTT_NOEXCEPT {
- return { view.begin(), &view };
- }
- [[nodiscard]] iterator end() const ENTT_NOEXCEPT {
- return { view.end(), &view };
- }
- [[nodiscard]] reverse_iterator rbegin() const ENTT_NOEXCEPT {
- return { view.rbegin(), &view };
- }
- [[nodiscard]] reverse_iterator rend() const ENTT_NOEXCEPT {
- return { view.rend(), &view };
- }
- private:
- const basic_view_impl view;
- };
- [[nodiscard]] const auto * candidate() const ENTT_NOEXCEPT {
- return (std::min)({ static_cast<const basic_common_type *>(std::get<storage_type<Component> *>(pools))... }, [](const auto *lhs, const auto *rhs) {
- return lhs->size() < rhs->size();
- });
- }
- [[nodiscard]] auto pools_to_unchecked_array() const ENTT_NOEXCEPT {
- std::size_t pos{};
- std::array<const basic_common_type *, sizeof...(Component) - 1u> other{};
- (static_cast<void>(std::get<storage_type<Component> *>(pools) == view ? void() : void(other[pos++] = std::get<storage_type<Component> *>(pools))), ...);
- return other;
- }
- [[nodiscard]] auto filter_to_array() const ENTT_NOEXCEPT {
- return std::array<const basic_common_type *, sizeof...(Exclude)>{std::get<const storage_type<Exclude> *>(filter)...};
- }
- template<typename Comp, typename It>
- [[nodiscard]] auto dispatch_get([[maybe_unused]] It &it, [[maybe_unused]] const Entity entt) const {
- if constexpr(std::is_same_v<typename std::iterator_traits<It>::value_type, typename storage_type<Comp>::value_type>) {
- return std::forward_as_tuple(*it);
- } else {
- return get_as_tuple(*std::get<storage_type<Comp> *>(pools), entt);
- }
- }
- template<typename Comp, typename Func>
- void traverse(Func func) const {
- if constexpr(std::is_void_v<decltype(std::get<storage_type<Comp> *>(pools)->get({}))>) {
- for(const auto entt: static_cast<const basic_common_type &>(*std::get<storage_type<Comp> *>(pools))) {
- if(Policy::accept(entt) && ((std::is_same_v<Comp, Component> || std::get<storage_type<Component> *>(pools)->contains(entt)) && ...)
- && (!std::get<const storage_type<Exclude> *>(filter)->contains(entt) && ...))
- {
- if constexpr(is_applicable_v<Func, decltype(std::tuple_cat(std::tuple<entity_type>{}, std::declval<basic_view_impl>().get({})))>) {
- std::apply(func, std::tuple_cat(std::make_tuple(entt), get(entt)));
- } else {
- std::apply(func, get(entt));
- }
- }
- }
- } else {
- auto it = std::get<storage_type<Comp> *>(pools)->begin();
- for(const auto entt: static_cast<const basic_common_type &>(*std::get<storage_type<Comp> *>(pools))) {
- if(Policy::accept(entt) && ((std::is_same_v<Comp, Component> || std::get<storage_type<Component> *>(pools)->contains(entt)) && ...)
- && (!std::get<const storage_type<Exclude> *>(filter)->contains(entt) && ...))
- {
- if constexpr(is_applicable_v<Func, decltype(std::tuple_cat(std::tuple<entity_type>{}, std::declval<basic_view_impl>().get({})))>) {
- std::apply(func, std::tuple_cat(std::make_tuple(entt), dispatch_get<Component>(it, entt)...));
- } else {
- std::apply(func, std::tuple_cat(dispatch_get<Component>(it, entt)...));
- }
- }
- ++it;
- }
- }
- }
- public:
- /*! @brief Underlying entity identifier. */
- using entity_type = Entity;
- /*! @brief Unsigned integer type. */
- using size_type = std::size_t;
- /*! @brief Bidirectional iterator type. */
- using iterator = internal::view_iterator<Policy, typename basic_common_type::iterator, sizeof...(Component) - 1u, sizeof...(Exclude)>;
- /*! @brief Reverse iterator type. */
- using reverse_iterator = internal::view_iterator<Policy, typename basic_common_type::reverse_iterator, sizeof...(Component) - 1u, sizeof...(Exclude)>;
- /*! @brief Iterable view type. */
- using iterable_view = iterable;
- /*! @brief Default constructor to use to create empty, invalid views. */
- basic_view_impl() ENTT_NOEXCEPT
- : 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_impl(storage_type<Component> &... component, const storage_type<Exclude> &... epool) ENTT_NOEXCEPT
- : pools{&component...},
- filter{&epool...},
- view{candidate()}
- {}
- /**
- * @brief Forces the type to use to drive iterations.
- * @tparam Comp Type of component to use to drive the iteration.
- */
- template<typename Comp>
- void use() const ENTT_NOEXCEPT {
- view = std::get<storage_type<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 {
- return iterator{view->begin(), view->end(), view->begin(), pools_to_unchecked_array(), filter_to_array()};
- }
- /**
- * @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 {
- return iterator{view->begin(), view->end(), view->end(), pools_to_unchecked_array(), filter_to_array()};
- }
- /**
- * @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 {
- return reverse_iterator{view->rbegin(), view->rend(), view->rbegin(), pools_to_unchecked_array(), filter_to_array()};
- }
- /**
- * @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 {
- return reverse_iterator{view->rbegin(), view->rend(), view->rend(), pools_to_unchecked_array(), filter_to_array()};
- }
- /**
- * @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 {
- 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 {
- const auto it = rbegin();
- return it != rend() ? *it : null;
- }
- /**
- * @brief Finds an entity.
- * @param entt A valid entity 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 {
- const auto it = iterator{view->begin(), view->end(), view->find(entt), pools_to_unchecked_array(), filter_to_array()};
- return (it != end() && *it == entt) ? it : end();
- }
- /**
- * @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 entity identifier.
- * @return True if the view contains the given entity, false otherwise.
- */
- [[nodiscard]] bool contains(const entity_type entt) const {
- return (std::get<storage_type<Component> *>(pools)->contains(entt) && ...) && (!std::get<const storage_type<Exclude> *>(filter)->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 view
- * results in undefined behavior.
- *
- * @tparam Comp Types of components to get.
- * @param entt A valid entity identifier.
- * @return The components assigned to the entity.
- */
- template<typename... Comp>
- [[nodiscard]] decltype(auto) get([[maybe_unused]] const entity_type entt) const {
- ENTT_ASSERT(contains(entt), "View does not contain entity");
- if constexpr(sizeof...(Comp) == 0) {
- return std::tuple_cat(get_as_tuple(*std::get<storage_type<Component> *>(pools), entt)...);
- } else if constexpr(sizeof...(Comp) == 1) {
- return (std::get<storage_type<Comp> *>(pools)->get(entt), ...);
- } else {
- return std::tuple_cat(get_as_tuple(*std::get<storage_type<Comp> *>(pools), 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 {
- ((std::get<storage_type<Component> *>(pools) == view ? traverse<Component>(std::move(func)) : void()), ...);
- }
- /**
- * @brief Iterates entities and components and applies the given function
- * object to them.
- *
- * The pool of the suggested component is used to lead the iterations. The
- * returned entities will therefore respect the order of the pool associated
- * with that type.
- *
- * @sa each
- *
- * @tparam Comp Type of component to use to drive the iteration.
- * @tparam Func Type of the function object to invoke.
- * @param func A valid function object.
- */
- template<typename Comp, typename Func>
- void each(Func func) const {
- use<Comp>();
- traverse<Comp>(std::move(func));
- }
- /**
- * @brief Returns an iterable object to use to _visit_ the view.
- *
- * 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 view.
- */
- [[nodiscard]] iterable_view each() const ENTT_NOEXCEPT {
- return iterable_view{*this};
- }
- /**
- * @brief Returns an iterable object to use to _visit_ the view.
- *
- * The pool of the suggested component is used to lead the iterations. The
- * returned elements will therefore respect the order of the pool associated
- * with that type.
- *
- * @sa each
- *
- * @tparam Comp Type of component to use to drive the iteration.
- * @return An iterable object to use to _visit_ the view.
- */
- template<typename Comp>
- [[nodiscard]] iterable_view each() const ENTT_NOEXCEPT {
- use<Comp>();
- return iterable_view{*this};
- }
- /**
- * @brief Combines two views in a _more specific_ one (friend function).
- * @tparam Id A valid entity type (see entt_traits for more details).
- * @tparam ELhs Filter list of the first view.
- * @tparam CLhs Component list of the first view.
- * @tparam ERhs Filter list of the second view.
- * @tparam CRhs Component list of the second view.
- * @return A more specific view.
- */
- template<typename Id, typename... ELhs, typename... CLhs, typename... ERhs, typename... CRhs>
- friend auto operator|(const basic_view<Id, exclude_t<ELhs...>, CLhs...> &, const basic_view<Id, exclude_t<ERhs...>, CRhs...> &);
- private:
- const std::tuple<storage_type<Component> *...> pools;
- const std::tuple<const storage_type<Exclude> *...> filter;
- mutable const basic_common_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.
- *
- * @note
- * Views share a reference to the underlying data structure 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 views.
- *
- * @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 Component Type of component iterated by the view.
- */
- template<typename Entity, typename Component>
- class basic_view_impl<packed_storage_policy, Entity, exclude_t<>, Component> {
- using basic_common_type = basic_sparse_set<Entity>;
- using storage_type = constness_as_t<typename storage_traits<Entity, std::remove_const_t<Component>>::storage_type, Component>;
- class iterable final {
- template<typename... It>
- struct iterable_iterator final {
- using difference_type = std::ptrdiff_t;
- using value_type = decltype(std::tuple_cat(std::tuple<Entity>{}, std::declval<basic_view_impl>().get({})));
- using pointer = void;
- using reference = value_type;
- using iterator_category = std::input_iterator_tag;
- template<typename... Discard>
- iterable_iterator(It... from, Discard...) ENTT_NOEXCEPT
- : it{from...}
- {}
- iterable_iterator & operator++() ENTT_NOEXCEPT {
- return (++std::get<It>(it), ...), *this;
- }
- iterable_iterator operator++(int) ENTT_NOEXCEPT {
- iterable_iterator orig = *this;
- return ++(*this), orig;
- }
- [[nodiscard]] reference operator*() const ENTT_NOEXCEPT {
- return { *std::get<It>(it)... };
- }
- [[nodiscard]] bool operator==(const iterable_iterator &other) const ENTT_NOEXCEPT {
- return std::get<0>(other.it) == std::get<0>(it);
- }
- [[nodiscard]] bool operator!=(const iterable_iterator &other) const ENTT_NOEXCEPT {
- return !(*this == other);
- }
- private:
- std::tuple<It...> it;
- };
- public:
- using iterator = std::conditional_t<
- std::is_void_v<decltype(std::declval<storage_type>().get({}))>,
- iterable_iterator<typename basic_common_type::iterator>,
- iterable_iterator<typename basic_common_type::iterator, decltype(std::declval<storage_type>().begin())>
- >;
- using reverse_iterator = std::conditional_t<
- std::is_void_v<decltype(std::declval<storage_type>().get({}))>,
- iterable_iterator<typename basic_common_type::reverse_iterator>,
- iterable_iterator<typename basic_common_type::reverse_iterator, decltype(std::declval<storage_type>().rbegin())>
- >;
- iterable(storage_type &ref)
- : pool{&ref}
- {}
- [[nodiscard]] iterator begin() const ENTT_NOEXCEPT {
- return iterator{pool->basic_common_type::begin(), pool->begin()};
- }
- [[nodiscard]] iterator end() const ENTT_NOEXCEPT {
- return iterator{pool->basic_common_type::end(), pool->end()};
- }
- [[nodiscard]] reverse_iterator rbegin() const ENTT_NOEXCEPT {
- return reverse_iterator{pool->basic_common_type::rbegin(), pool->rbegin()};
- }
- [[nodiscard]] reverse_iterator rend() const ENTT_NOEXCEPT {
- return reverse_iterator{pool->basic_common_type::rend(), pool->rend()};
- }
- private:
- storage_type * const pool;
- };
- 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_common_type::iterator;
- /*! @brief Reversed iterator type. */
- using reverse_iterator = typename basic_common_type::reverse_iterator;
- /*! @brief Iterable view type. */
- using iterable_view = iterable;
- /*! @brief Default constructor to use to create empty, invalid views. */
- basic_view_impl() ENTT_NOEXCEPT
- : pools{},
- filter{}
- {}
- /**
- * @brief Constructs a single-type view from a storage class.
- * @param ref The storage for the type to iterate.
- */
- basic_view_impl(storage_type &ref) ENTT_NOEXCEPT
- : pools{&ref},
- filter{}
- {}
- /**
- * @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 std::get<0>(pools)->size();
- }
- /**
- * @brief Checks whether a view is empty.
- * @return True if the view is empty, false otherwise.
- */
- [[nodiscard]] bool empty() const ENTT_NOEXCEPT {
- return std::get<0>(pools)->empty();
- }
- /**
- * @brief Direct access to the raw representation offered by the storage.
- * @return A pointer to the array of components.
- */
- [[nodiscard]] auto raw() const ENTT_NOEXCEPT {
- return std::get<0>(pools)->raw();
- }
- /**
- * @brief Direct access to the list of entities.
- *
- * The returned pointer is such that range `[data(), data() + size())` is
- * always a valid range, even if the container is empty.
- *
- * @return A pointer to the array of entities.
- */
- [[nodiscard]] auto data() const ENTT_NOEXCEPT {
- return std::get<0>(pools)->data();
- }
- /**
- * @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 std::get<0>(pools)->basic_common_type::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 std::get<0>(pools)->basic_common_type::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 std::get<0>(pools)->basic_common_type::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 std::get<0>(pools)->basic_common_type::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 {
- 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 {
- const auto it = rbegin();
- return it != rend() ? *it : null;
- }
- /**
- * @brief Finds an entity.
- * @param entt A valid entity 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 {
- const auto it = std::get<0>(pools)->find(entt);
- 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 view is properly initialized.
- * @return True if the view is properly initialized, false otherwise.
- */
- [[nodiscard]] explicit operator bool() const ENTT_NOEXCEPT {
- return std::get<0>(pools) != nullptr;
- }
- /**
- * @brief Checks if a view contains an entity.
- * @param entt A valid entity identifier.
- * @return True if the view contains the given entity, false otherwise.
- */
- [[nodiscard]] bool contains(const entity_type entt) const {
- return std::get<0>(pools)->contains(entt);
- }
- /**
- * @brief Returns the component 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 view
- * results in undefined behavior.
- *
- * @tparam Comp Types of components to get.
- * @param entt A valid entity 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 get_as_tuple(*std::get<0>(pools), entt);
- } else {
- static_assert(std::is_same_v<Comp..., Component>, "Invalid component type");
- 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
- *
- * @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 {
- if constexpr(std::is_void_v<decltype(std::get<0>(pools)->get({}))>) {
- if constexpr(std::is_invocable_v<Func>) {
- for(auto pos = size(); pos; --pos) {
- func();
- }
- } else {
- for(auto entity: *this) {
- func(entity);
- }
- }
- } else {
- if constexpr(is_applicable_v<Func, decltype(*each().begin())>) {
- for(const auto pack: each()) {
- std::apply(func, pack);
- }
- } else {
- for(auto &&component: *std::get<0>(pools)) {
- func(component);
- }
- }
- }
- }
- /**
- * @brief Returns an iterable object to use to _visit_ the view.
- *
- * The iterable object returns tuples that contain the current entity and a
- * reference to its component if it's a non-empty one. The _constness_ of
- * the component 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 view.
- */
- [[nodiscard]] iterable_view each() const ENTT_NOEXCEPT {
- return iterable_view{*std::get<0>(pools)};
- }
- /**
- * @brief Combines two views in a _more specific_ one (friend function).
- * @tparam Id A valid entity type (see entt_traits for more details).
- * @tparam ELhs Filter list of the first view.
- * @tparam CLhs Component list of the first view.
- * @tparam ERhs Filter list of the second view.
- * @tparam CRhs Component list of the second view.
- * @return A more specific view.
- */
- template<typename Id, typename... ELhs, typename... CLhs, typename... ERhs, typename... CRhs>
- friend auto operator|(const basic_view<Id, exclude_t<ELhs...>, CLhs...> &, const basic_view<Id, exclude_t<ERhs...>, CRhs...> &);
- private:
- const std::tuple<storage_type *> pools;
- const std::tuple<> filter;
- };
- /**
- * @brief View implementation dispatcher.
- * @tparam Entity A valid entity type (see entt_traits for more details).
- * @tparam Exclude Types of components used to filter the view.
- * @tparam Component Types of components iterated by the view.
- */
- template<typename Entity, typename... Exclude, typename... Component>
- struct basic_view<Entity, exclude_t<Exclude...>, Component...>
- : basic_view_impl<std::conditional_t<std::disjunction_v<typename component_traits<std::remove_const_t<Component>>::in_place_delete...>, stable_storage_policy, packed_storage_policy>, Entity, exclude_t<Exclude...>, Component...>
- {
- /*! @brief Most restrictive storage policy of all component types. */
- using storage_policy = std::conditional_t<std::disjunction_v<typename component_traits<std::remove_const_t<Component>>::in_place_delete...>, stable_storage_policy, packed_storage_policy>;
- using basic_view_impl<storage_policy, Entity, exclude_t<Exclude...>, Component...>::basic_view_impl;
- };
- /**
- * @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...>, entt::exclude_t<>, constness_as_t<typename Storage::value_type, Storage>...>;
- /**
- * @brief Combines two views in a _more specific_ one.
- * @tparam Entity A valid entity type (see entt_traits for more details).
- * @tparam ELhs Filter list of the first view.
- * @tparam CLhs Component list of the first view.
- * @tparam ERhs Filter list of the second view.
- * @tparam CRhs Component list of the second view.
- * @param lhs A valid reference to the first view.
- * @param rhs A valid reference to the second view.
- * @return A more specific view.
- */
- template<typename Entity, typename... ELhs, typename... CLhs, typename... ERhs, typename... CRhs>
- [[nodiscard]] auto operator|(const basic_view<Entity, exclude_t<ELhs...>, CLhs...> &lhs, const basic_view<Entity, exclude_t<ERhs...>, CRhs...> &rhs) {
- using view_type = basic_view<Entity, exclude_t<ELhs..., ERhs...>, CLhs..., CRhs...>;
- return std::apply([](auto *... storage) { return view_type{*storage...}; }, std::tuple_cat(lhs.pools, rhs.pools, lhs.filter, rhs.filter));
- }
- }
- #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
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_NOEXCEPT noexcept
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_NOEXCEPT
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606L
- # include <new>
- # define ENTT_LAUNDER(expr) std::launder(expr)
- #else
- # define ENTT_LAUNDER(expr) expr
- #endif
- #ifndef ENTT_USE_ATOMIC
- # define ENTT_MAYBE_ATOMIC(Type) Type
- #else
- # include <atomic>
- # define ENTT_MAYBE_ATOMIC(Type) std::atomic<Type>
- #endif
- #ifndef ENTT_ID_TYPE
- # include <cstdint>
- # define ENTT_ID_TYPE std::uint32_t
- #endif
- #ifdef ENTT_SPARSE_PAGE
- static_assert(ENTT_SPARSE_PAGE && ((ENTT_SPARSE_PAGE & (ENTT_SPARSE_PAGE - 1)) == 0), "ENTT_SPARSE_PAGE must be a power of two");
- #else
- # define ENTT_SPARSE_PAGE 4096
- #endif
- #ifdef ENTT_PACKED_PAGE
- static_assert(ENTT_PACKED_PAGE && ((ENTT_PACKED_PAGE & (ENTT_PACKED_PAGE - 1)) == 0), "ENTT_PACKED_PAGE must be a power of two");
- #else
- # 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
- # include <type_traits>
- # define ENTT_IGNORE_IF_EMPTY std::false_type
- #else
- # include <type_traits>
- # define ENTT_IGNORE_IF_EMPTY std::true_type
- #endif
- #ifndef ENTT_STANDARD_CPP
- # 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
- #endif
- namespace entt {
- /**
- * @brief Service locator, nothing more.
- *
- * A service locator can be 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 template
- * based implementation tries to fill the gap and to get rid of the burden of
- * defining a different specific locator for each application.
- *
- * @tparam Service Type of service managed by the locator.
- */
- template<typename Service>
- struct service_locator {
- /*! @brief Type of service offered. */
- using service_type = Service;
- /*! @brief Default constructor, deleted on purpose. */
- service_locator() = delete;
- /*! @brief Default destructor, deleted on purpose. */
- ~service_locator() = delete;
- /**
- * @brief Tests if a valid service implementation is set.
- * @return True if the service is set, false otherwise.
- */
- [[nodiscard]] static bool empty() ENTT_NOEXCEPT {
- return !static_cast<bool>(service);
- }
- /**
- * @brief Returns a weak pointer to a service implementation, if any.
- *
- * Clients of a service shouldn't retain references to it. The recommended
- * way is to retrieve the service implementation currently set each and
- * every time the need of using it arises. Otherwise users can incur in
- * unexpected behaviors.
- *
- * @return A reference to the service implementation currently set, if any.
- */
- [[nodiscard]] static std::weak_ptr<Service> get() ENTT_NOEXCEPT {
- return service;
- }
- /**
- * @brief Returns a weak reference to a service implementation, if any.
- *
- * Clients of a service shouldn't retain references to it. The recommended
- * way is to retrieve the service implementation currently set each and
- * every time the need of using it arises. Otherwise users can incur in
- * unexpected behaviors.
- *
- * @warning
- * In case no service implementation has been set, a call to this function
- * results in undefined behavior.
- *
- * @return A reference to the service implementation currently set, if any.
- */
- [[nodiscard]] static Service & ref() ENTT_NOEXCEPT {
- return *service;
- }
- /**
- * @brief Sets or replaces a service.
- * @tparam Impl Type of the new service to use.
- * @tparam Args Types of arguments to use to construct the service.
- * @param args Parameters to use to construct the service.
- */
- template<typename Impl = Service, typename... Args>
- static void set(Args &&... args) {
- service = std::make_shared<Impl>(std::forward<Args>(args)...);
- }
- /**
- * @brief Sets or replaces a service.
- * @param ptr Service to use to replace the current one.
- */
- static void set(std::shared_ptr<Service> ptr) {
- ENTT_ASSERT(static_cast<bool>(ptr), "Null service not allowed");
- service = std::move(ptr);
- }
- /**
- * @brief Resets a service.
- *
- * The service is no longer valid after a reset.
- */
- static void reset() {
- service.reset();
- }
- private:
- inline static std::shared_ptr<Service> service = nullptr;
- };
- }
- #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);
- }
- };
- }
- #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 <utility>
- #include <vector>
- // #include "../config/config.h"
- #ifndef ENTT_CONFIG_CONFIG_H
- #define ENTT_CONFIG_CONFIG_H
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_NOEXCEPT noexcept
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_NOEXCEPT
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606L
- # include <new>
- # define ENTT_LAUNDER(expr) std::launder(expr)
- #else
- # define ENTT_LAUNDER(expr) expr
- #endif
- #ifndef ENTT_USE_ATOMIC
- # define ENTT_MAYBE_ATOMIC(Type) Type
- #else
- # include <atomic>
- # define ENTT_MAYBE_ATOMIC(Type) std::atomic<Type>
- #endif
- #ifndef ENTT_ID_TYPE
- # include <cstdint>
- # define ENTT_ID_TYPE std::uint32_t
- #endif
- #ifdef ENTT_SPARSE_PAGE
- static_assert(ENTT_SPARSE_PAGE && ((ENTT_SPARSE_PAGE & (ENTT_SPARSE_PAGE - 1)) == 0), "ENTT_SPARSE_PAGE must be a power of two");
- #else
- # define ENTT_SPARSE_PAGE 4096
- #endif
- #ifdef ENTT_PACKED_PAGE
- static_assert(ENTT_PACKED_PAGE && ((ENTT_PACKED_PAGE & (ENTT_PACKED_PAGE - 1)) == 0), "ENTT_PACKED_PAGE must be a power of two");
- #else
- # 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
- # include <type_traits>
- # define ENTT_IGNORE_IF_EMPTY std::false_type
- #else
- # include <type_traits>
- # define ENTT_IGNORE_IF_EMPTY std::true_type
- #endif
- #ifndef ENTT_STANDARD_CPP
- # 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
- #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
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_NOEXCEPT noexcept
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_NOEXCEPT
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606L
- # include <new>
- # define ENTT_LAUNDER(expr) std::launder(expr)
- #else
- # define ENTT_LAUNDER(expr) expr
- #endif
- #ifndef ENTT_USE_ATOMIC
- # define ENTT_MAYBE_ATOMIC(Type) Type
- #else
- # include <atomic>
- # define ENTT_MAYBE_ATOMIC(Type) std::atomic<Type>
- #endif
- #ifndef ENTT_ID_TYPE
- # include <cstdint>
- # define ENTT_ID_TYPE std::uint32_t
- #endif
- #ifdef ENTT_SPARSE_PAGE
- static_assert(ENTT_SPARSE_PAGE && ((ENTT_SPARSE_PAGE & (ENTT_SPARSE_PAGE - 1)) == 0), "ENTT_SPARSE_PAGE must be a power of two");
- #else
- # define ENTT_SPARSE_PAGE 4096
- #endif
- #ifdef ENTT_PACKED_PAGE
- static_assert(ENTT_PACKED_PAGE && ((ENTT_PACKED_PAGE & (ENTT_PACKED_PAGE - 1)) == 0), "ENTT_PACKED_PAGE must be a power of two");
- #else
- # 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
- # include <type_traits>
- # define ENTT_IGNORE_IF_EMPTY std::false_type
- #else
- # include <type_traits>
- # define ENTT_IGNORE_IF_EMPTY std::true_type
- #endif
- #ifndef ENTT_STANDARD_CPP
- # 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
- #endif
- // #include "fwd.hpp"
- #ifndef ENTT_CORE_FWD_HPP
- #define ENTT_CORE_FWD_HPP
- #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<>;
- }
- #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<class 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_t = 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_v = 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::disjunction_v<std::is_same<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<class 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;
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- namespace internal {
- template<typename>
- [[nodiscard]] constexpr bool is_equality_comparable(...) { return false; }
- template<typename Type>
- [[nodiscard]] constexpr auto is_equality_comparable(choice_t<0>)
- -> decltype(std::declval<Type>() == std::declval<Type>()) { return true; }
- template<typename Type>
- [[nodiscard]] constexpr auto is_equality_comparable(choice_t<1>)
- -> decltype(std::declval<typename Type::value_type>(), std::declval<Type>() == std::declval<Type>()) {
- if constexpr(std::is_same_v<typename Type::value_type, Type>) {
- return is_equality_comparable<Type>(choice<0>);
- } else {
- return is_equality_comparable<typename Type::value_type>(choice<2>);
- }
- }
- template<typename Type>
- [[nodiscard]] constexpr auto is_equality_comparable(choice_t<2>)
- -> decltype(std::declval<typename Type::mapped_type>(), std::declval<Type>() == std::declval<Type>()) {
- return is_equality_comparable<typename Type::key_type>(choice<2>) && is_equality_comparable<typename Type::mapped_type>(choice<2>);
- }
- }
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /**
- * @brief Provides the member constant `value` to true if a given type is
- * equality comparable, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_equality_comparable: std::bool_constant<internal::is_equality_comparable<Type>(choice<2>)> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<class Type>
- inline constexpr bool is_equality_comparable_v = is_equality_comparable<Type>::value;
- /*! @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 {};
- /*! @copydoc is_iterator */
- template<typename Type>
- struct is_iterator<Type, std::void_t<typename std::iterator_traits<Type>::iterator_category>>
- : std::true_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 of the
- * required iterator type, false otherwise.
- * @tparam Type The type to test.
- * @tparam It Required iterator type.
- */
- template<typename Type, typename It, typename = void>
- struct is_iterator_type: std::false_type {};
- /*! @copydoc is_iterator_type */
- template<typename Type, typename It>
- struct is_iterator_type<Type, It, std::enable_if_t<is_iterator_v<Type> && std::is_same_v<Type, It>>>
- : std::true_type
- {};
- /*! @copydoc is_iterator_type */
- template<typename Type, typename It>
- struct is_iterator_type<Type, It, std::enable_if_t<!std::is_same_v<Type, It>, std::void_t<typename It::iterator_type>>>
- : is_iterator_type<Type, typename It::iterator_type>
- {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- * @tparam It Required iterator type.
- */
- template<typename Type, typename It>
- inline constexpr bool is_iterator_type_v = is_iterator_type<Type, It>::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;
- }
- #endif
- // #include "type_traits.hpp"
- #ifndef ENTT_META_TYPE_TRAITS_HPP
- #define ENTT_META_TYPE_TRAITS_HPP
- #include <type_traits>
- 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 meta associative
- * container claims to wrap a key-only type, false otherwise.
- * @tparam Type Potentially key-only meta associative container type.
- */
- template<typename, typename = void>
- struct is_key_only_meta_associative_container: std::true_type {};
- /*! @copydoc is_key_only_meta_associative_container */
- template<typename Type>
- struct is_key_only_meta_associative_container<Type, std::void_t<typename meta_associative_container_traits<Type>::type::mapped_type>>
- : std::false_type
- {};
- /**
- * @brief Helper variable template.
- * @tparam Type Potentially key-only meta associative container type.
- */
- template<typename Type>
- inline constexpr auto is_key_only_meta_associative_container_v = is_key_only_meta_associative_container<Type>::value;
- /**
- * @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;
- }
- #endif
- namespace entt {
- /**
- * @brief Container traits.
- * @tparam Container Type of the underlying container.
- * @tparam Trait Traits associated with the underlying container.
- */
- template<typename Container, template<typename> class... Trait>
- struct meta_container_traits: public Trait<Container>... {
- /*! @brief Type of container. */
- using type = Container;
- };
- /**
- * @brief Basic STL-compatible container traits
- * @tparam Container The type of the container.
- */
- template<typename Container>
- struct basic_container {
- /**
- * @brief Returns the size of the given container.
- * @param cont The container for which to return the size.
- * @return The size of the given container.
- */
- [[nodiscard]] static typename Container::size_type size(const Container &cont) ENTT_NOEXCEPT {
- return cont.size();
- }
- /**
- * @brief Returns an iterator to the first element of the given container.
- * @param cont The container for which to return the iterator.
- * @return An iterator to the first element of the given container.
- */
- [[nodiscard]] static typename Container::iterator begin(Container &cont) {
- return cont.begin();
- }
- /**
- * @brief Returns an iterator to the first element of the given container.
- * @param cont The container for which to return the iterator.
- * @return An iterator to the first element of the given container.
- */
- [[nodiscard]] static typename Container::const_iterator cbegin(const Container &cont) {
- return cont.begin();
- }
- /**
- * @brief Returns an iterator past the last element of the given container.
- * @param cont The container for which to return the iterator.
- * @return An iterator past the last element of the given container.
- */
- [[nodiscard]] static typename Container::iterator end(Container &cont) {
- return cont.end();
- }
- /**
- * @brief Returns an iterator past the last element of the given container.
- * @param cont The container for which to return the iterator.
- * @return An iterator past the last element of the given container.
- */
- [[nodiscard]] static typename Container::const_iterator cend(const Container &cont) {
- return cont.end();
- }
- };
- /**
- * @brief Basic STL-compatible associative container traits
- * @tparam Container The type of the container.
- */
- template<typename Container>
- struct basic_associative_container {
- /**
- * @brief Returns an iterator to the element with key equivalent to the
- * given one, if any.
- * @param cont The container in which to search for the element.
- * @param key The key of the element to search.
- * @return An iterator to the element with the given key, if any.
- */
- [[nodiscard]] static typename Container::iterator find(Container &cont, const typename Container::key_type &key) {
- return cont.find(key);
- }
- /*! @copydoc find */
- [[nodiscard]] static typename Container::const_iterator cfind(const Container &cont, const typename Container::key_type &key) {
- return cont.find(key);
- }
- };
- /**
- * @brief Basic STL-compatible dynamic container traits
- * @tparam Container The type of the container.
- */
- template<typename Container>
- struct basic_dynamic_container {
- /**
- * @brief Clears the content of the given container.
- * @param cont The container for which to clear the content.
- * @return True in case of success, false otherwise.
- */
- [[nodiscard]] static bool clear([[maybe_unused]] Container &cont) {
- return cont.clear(), true;
- }
- };
- /**
- * @brief Basic STL-compatible dynamic associative container traits
- * @tparam Container The type of the container.
- */
- template<typename Container>
- struct basic_dynamic_associative_container {
- /**
- * @brief Removes the specified element from the given container.
- * @param cont The container from which to remove the element.
- * @param key The element to remove.
- * @return A bool denoting whether the removal took place.
- */
- [[nodiscard]] static bool erase([[maybe_unused]] Container &cont, [[maybe_unused]] const typename Container::key_type &key) {
- const auto sz = cont.size();
- return cont.erase(key) != sz;
- }
- };
- /**
- * @brief Basic STL-compatible sequence container traits
- * @tparam Container The type of the container.
- */
- template<typename Container>
- struct basic_sequence_container {
- /**
- * @brief Returns a reference to the element at the specified location of
- * the given container (no bounds checking is performed).
- * @param cont The container from which to get the element.
- * @param pos The position of the element to return.
- * @return A reference to the requested element.
- */
- [[nodiscard]] static typename Container::reference get(Container &cont, typename Container::size_type pos) {
- return cont[pos];
- }
- /*! @copydoc get */
- [[nodiscard]] static typename Container::const_reference cget(const Container &cont, typename Container::size_type pos) {
- return cont[pos];
- }
- };
- /**
- * @brief STL-compatible dynamic associative key-only container traits
- * @tparam Container The type of the container.
- */
- template<typename Container>
- struct dynamic_associative_key_only_container {
- /**
- * @brief Inserts an element into the given container.
- * @param cont The container in which to insert the element.
- * @param key The element to insert.
- * @return A bool denoting whether the insertion took place.
- */
- [[nodiscard]] static bool insert([[maybe_unused]] Container &cont, [[maybe_unused]] const typename Container::key_type &key) {
- return cont.insert(key).second;
- }
- };
- /**
- * @brief STL-compatible dynamic key-value associative container traits
- * @tparam Container The type of the container.
- */
- template<typename Container>
- struct dynamic_associative_key_value_container {
- /**
- * @brief Inserts an element (a key/value pair) into the given container.
- * @param cont The container in which to insert the element.
- * @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.
- */
- [[nodiscard]] static bool insert([[maybe_unused]] Container &cont, [[maybe_unused]] const typename Container::key_type &key, [[maybe_unused]] const typename Container::mapped_type &value) {
- return cont.insert(std::make_pair(key, value)).second;
- }
- };
- /**
- * @brief STL-compatible dynamic sequence container traits
- * @tparam Container The type of the container.
- */
- template<typename Container>
- struct dynamic_sequence_container {
- /**
- * @brief Resizes the given container to contain the given number of
- * elements.
- * @param cont The container to resize.
- * @param sz The new size of the container.
- * @return True in case of success, false otherwise.
- */
- [[nodiscard]] static bool resize([[maybe_unused]] Container &cont, [[maybe_unused]] typename Container::size_type sz) {
- return cont.resize(sz), true;
- }
- /**
- * @brief Inserts an element at the specified location of the given
- * container.
- * @param cont The container into which to insert the element.
- * @param it Iterator before which the element will be inserted.
- * @param value Element value to insert.
- * @return A pair consisting of an iterator to the inserted element (in case
- * of success) and a bool denoting whether the insertion took place.
- */
- [[nodiscard]] static std::pair<typename Container::iterator, bool> insert([[maybe_unused]] Container &cont, [[maybe_unused]] typename Container::const_iterator it, [[maybe_unused]] const typename Container::value_type &value) {
- return { cont.insert(it, value), true };
- }
- /**
- * @brief Removes the element at the specified location from the given
- * container.
- * @param cont The container from which to remove the element.
- * @param it Iterator to the element to remove.
- * @return A pair consisting of an iterator following the last removed
- * element (in case of success) and a bool denoting whether the insertion
- * took place.
- */
- [[nodiscard]] static std::pair<typename Container::iterator, bool> erase([[maybe_unused]] Container &cont, [[maybe_unused]] typename Container::const_iterator it) {
- return { cont.erase(it), true };
- }
- };
- /**
- * @brief STL-compatible fixed sequence container traits
- * @tparam Container The type of the container.
- */
- template<typename Container>
- struct fixed_sequence_container {
- /**
- * @brief Does nothing.
- * @return False to indicate failure in all cases.
- */
- [[nodiscard]] static bool resize(const Container &, typename Container::size_type) {
- return false;
- }
- /**
- * @brief Does nothing.
- * @return False to indicate failure in all cases.
- */
- [[nodiscard]] static bool clear(const Container &) {
- return false;
- }
- /**
- * @brief Does nothing.
- * @return A pair consisting of an invalid iterator and a false value to
- * indicate failure in all cases.
- */
- [[nodiscard]] static std::pair<typename Container::iterator, bool> insert(const Container &, typename Container::const_iterator, const typename Container::value_type &) {
- return { {}, false };
- }
- /**
- * @brief Does nothing.
- * @return A pair consisting of an invalid iterator and a false value to
- * indicate failure in all cases.
- */
- [[nodiscard]] static std::pair<typename Container::iterator, bool> erase(const Container &, typename Container::const_iterator) {
- return { {}, false };
- }
- };
- /**
- * @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...>>
- : meta_container_traits<
- std::vector<Type, Args...>,
- basic_container,
- basic_dynamic_container,
- basic_sequence_container,
- dynamic_sequence_container
- >
- {};
- /**
- * @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>>
- : meta_container_traits<
- std::array<Type, N>,
- basic_container,
- basic_sequence_container,
- fixed_sequence_container
- >
- {};
- /**
- * @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...>>
- : meta_container_traits<
- std::map<Key, Value, Args...>,
- basic_container,
- basic_associative_container,
- basic_dynamic_container,
- basic_dynamic_associative_container,
- dynamic_associative_key_value_container
- >
- {};
- /**
- * @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...>>
- : meta_container_traits<
- std::unordered_map<Key, Value, Args...>,
- basic_container,
- basic_associative_container,
- basic_dynamic_container,
- basic_dynamic_associative_container,
- dynamic_associative_key_value_container
- >
- {};
- /**
- * @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...>>
- : meta_container_traits<
- std::set<Key, Args...>,
- basic_container,
- basic_associative_container,
- basic_dynamic_container,
- basic_dynamic_associative_container,
- dynamic_associative_key_only_container
- >
- {};
- /**
- * @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...>>
- : meta_container_traits<
- std::unordered_set<Key, Args...>,
- basic_container,
- basic_associative_container,
- basic_dynamic_container,
- basic_dynamic_associative_container,
- dynamic_associative_key_only_container
- >
- {};
- }
- #endif
- // #include "meta/ctx.hpp"
- #ifndef ENTT_META_CTX_HPP
- #define ENTT_META_CTX_HPP
- // #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 "../config/config.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;
- }
- };
- }
- /**
- * 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()};
- };
- }
- #endif
- // #include "meta/factory.hpp"
- #ifndef ENTT_META_FACTORY_HPP
- #define ENTT_META_FACTORY_HPP
- #include <cstddef>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- // #include "../core/fwd.hpp"
- #ifndef ENTT_CORE_FWD_HPP
- #define ENTT_CORE_FWD_HPP
- #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<>;
- }
- #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 "../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 "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;
- };
- }
- /**
- * 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 identifers 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.
- *
- * @tparam Char Character type.
- */
- template<typename Char>
- class basic_hashed_string {
- using traits_type = internal::fnv1a_traits<id_type>;
- struct const_wrapper {
- // non-explicit constructor on purpose
- constexpr const_wrapper(const Char *curr) ENTT_NOEXCEPT: str{curr} {}
- const Char *str;
- };
- // Fowler–Noll–Vo hash function v. 1a - the good
- [[nodiscard]] static constexpr id_type helper(const Char *curr) ENTT_NOEXCEPT {
- auto value = traits_type::offset;
- while(*curr != 0) {
- value = (value ^ static_cast<traits_type::type>(*(curr++))) * traits_type::prime;
- }
- return value;
- }
- public:
- /*! @brief Character type. */
- using value_type = Char;
- /*! @brief Unsigned integer type. */
- using hash_type = id_type;
- /**
- * @brief Returns directly the numeric representation of a string view.
- * @param str Human-readable identifer.
- * @param size Length of the string to hash.
- * @return The numeric representation of the string.
- */
- [[nodiscard]] static constexpr hash_type value(const value_type *str, std::size_t size) ENTT_NOEXCEPT {
- id_type partial{traits_type::offset};
- while(size--) { partial = (partial^(str++)[0])*traits_type::prime; }
- return partial;
- }
- /**
- * @brief Returns directly the numeric representation of a string.
- *
- * Forcing template resolution avoids implicit conversions. An
- * human-readable identifier can be anything but a plain, old bunch of
- * characters.<br/>
- * Example of use:
- * @code{.cpp}
- * const auto value = basic_hashed_string<char>::to_value("my.png");
- * @endcode
- *
- * @tparam N Number of characters of the identifier.
- * @param str Human-readable identifer.
- * @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 helper(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 hash_type value(const_wrapper wrapper) ENTT_NOEXCEPT {
- return helper(wrapper.str);
- }
- /*! @brief Constructs an empty hashed string. */
- constexpr basic_hashed_string() ENTT_NOEXCEPT
- : str{nullptr}, hash{}
- {}
- /**
- * @brief Constructs a hashed string from an array of const characters.
- *
- * Forcing template resolution avoids implicit conversions. An
- * human-readable identifier can be anything but a plain, old bunch of
- * characters.<br/>
- * Example of use:
- * @code{.cpp}
- * basic_hashed_string<char> hs{"my.png"};
- * @endcode
- *
- * @tparam N Number of characters of the identifier.
- * @param curr Human-readable identifer.
- */
- template<std::size_t N>
- constexpr basic_hashed_string(const value_type (&curr)[N]) ENTT_NOEXCEPT
- : str{curr}, hash{helper(curr)}
- {}
- /**
- * @brief Explicit constructor on purpose to avoid constructing a hashed
- * string directly from a `const value_type *`.
- * @param wrapper Helps achieving the purpose by relying on overloading.
- */
- explicit constexpr basic_hashed_string(const_wrapper wrapper) ENTT_NOEXCEPT
- : str{wrapper.str}, hash{helper(wrapper.str)}
- {}
- /**
- * @brief Returns the human-readable representation of a hashed string.
- * @return The string used to initialize the instance.
- */
- [[nodiscard]] constexpr const value_type * data() const ENTT_NOEXCEPT {
- return str;
- }
- /**
- * @brief Returns the numeric representation of a hashed string.
- * @return The numeric representation of the instance.
- */
- [[nodiscard]] constexpr hash_type value() const ENTT_NOEXCEPT {
- return 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 instance.
- */
- [[nodiscard]] constexpr operator hash_type() const ENTT_NOEXCEPT { return value(); }
- /**
- * @brief Compares two hashed strings.
- * @param other Hashed string with which to compare.
- * @return True if the two hashed strings are identical, false otherwise.
- */
- [[nodiscard]] constexpr bool operator==(const basic_hashed_string &other) const ENTT_NOEXCEPT {
- return hash == other.hash;
- }
- private:
- const value_type *str;
- hash_type hash;
- };
- /**
- * @brief Deduction guide.
- *
- * It allows to deduce the character type of the hashed string directly from a
- * human-readable identifer provided to the constructor.
- *
- * @tparam Char Character type.
- * @tparam N Number of characters of the identifier.
- * @param str Human-readable identifer.
- */
- 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 == 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 entt::hashed_string operator"" _hs(const char *str, std::size_t) ENTT_NOEXCEPT {
- return entt::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 entt::hashed_wstring operator"" _hws(const wchar_t *str, std::size_t) ENTT_NOEXCEPT {
- return entt::hashed_wstring{str};
- }
- }
- }
- #endif
- // #include "fwd.hpp"
- namespace entt {
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- namespace internal {
- struct ENTT_API type_seq 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;
- }
- }
- /**
- * 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_seq 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_seq::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_seq<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. */
- class type_info final {
- template<typename>
- friend type_info type_id() ENTT_NOEXCEPT;
- type_info(id_type seq_v, id_type hash_v, std::string_view name_v) ENTT_NOEXCEPT
- : seq_value{seq_v},
- hash_value{hash_v},
- name_value{name_v}
- {}
- public:
- /*! @brief Default constructor. */
- type_info() ENTT_NOEXCEPT
- : type_info({}, {}, {})
- {}
- /*! @brief Default copy constructor. */
- type_info(const type_info &) ENTT_NOEXCEPT = default;
- /*! @brief Default move constructor. */
- type_info(type_info &&) ENTT_NOEXCEPT = default;
- /**
- * @brief Default copy assignment operator.
- * @return This type info object.
- */
- type_info & operator=(const type_info &) ENTT_NOEXCEPT = default;
- /**
- * @brief Default move assignment operator.
- * @return This type info object.
- */
- type_info & operator=(type_info &&) ENTT_NOEXCEPT = default;
- /**
- * @brief Checks if a type info object is properly initialized.
- * @return True if the object is properly initialized, false otherwise.
- */
- [[nodiscard]] explicit operator bool() const ENTT_NOEXCEPT {
- return name_value.data() != nullptr;
- }
- /**
- * @brief Type sequential identifier.
- * @return Type sequential identifier.
- */
- [[nodiscard]] id_type seq() const ENTT_NOEXCEPT {
- return seq_value;
- }
- /**
- * @brief Type hash.
- * @return Type hash.
- */
- [[nodiscard]] id_type hash() const ENTT_NOEXCEPT {
- return hash_value;
- }
- /**
- * @brief Type name.
- * @return Type name.
- */
- [[nodiscard]] std::string_view name() const ENTT_NOEXCEPT {
- return name_value;
- }
- /**
- * @brief Compares the contents of two type info objects.
- * @param other Object with which to compare.
- * @return False if the two contents differ, true otherwise.
- */
- [[nodiscard]] bool operator==(const type_info &other) const ENTT_NOEXCEPT {
- return hash_value == other.hash_value;
- }
- private:
- id_type seq_value;
- id_type hash_value;
- std::string_view name_value;
- };
- /**
- * @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 contents differ, false otherwise.
- */
- [[nodiscard]] inline bool operator!=(const type_info &lhs, const type_info &rhs) ENTT_NOEXCEPT {
- return !(lhs == rhs);
- }
- /**
- * @brief Returns the type info object for a given type.
- * @tparam Type Type for which to generate a type info object.
- * @return The type info object for the given type.
- */
- template<typename Type>
- [[nodiscard]] type_info type_id() ENTT_NOEXCEPT {
- return type_info{
- type_seq<std::remove_cv_t<std::remove_reference_t<Type>>>::value(),
- type_hash<std::remove_cv_t<std::remove_reference_t<Type>>>::value(),
- type_name<std::remove_cv_t<std::remove_reference_t<Type>>>::value()
- };
- }
- }
- #endif
- // #include "../core/type_traits.hpp"
- // #include "meta.hpp"
- #ifndef ENTT_META_META_HPP
- #define ENTT_META_META_HPP
- #include <cstddef>
- #include <functional>
- #include <iterator>
- #include <memory>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- // #include "../core/any.hpp"
- #ifndef ENTT_CORE_ANY_HPP
- #define ENTT_CORE_ANY_HPP
- #include <cstddef>
- #include <functional>
- #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
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_NOEXCEPT noexcept
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_NOEXCEPT
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606L
- # include <new>
- # define ENTT_LAUNDER(expr) std::launder(expr)
- #else
- # define ENTT_LAUNDER(expr) expr
- #endif
- #ifndef ENTT_USE_ATOMIC
- # define ENTT_MAYBE_ATOMIC(Type) Type
- #else
- # include <atomic>
- # define ENTT_MAYBE_ATOMIC(Type) std::atomic<Type>
- #endif
- #ifndef ENTT_ID_TYPE
- # include <cstdint>
- # define ENTT_ID_TYPE std::uint32_t
- #endif
- #ifdef ENTT_SPARSE_PAGE
- static_assert(ENTT_SPARSE_PAGE && ((ENTT_SPARSE_PAGE & (ENTT_SPARSE_PAGE - 1)) == 0), "ENTT_SPARSE_PAGE must be a power of two");
- #else
- # define ENTT_SPARSE_PAGE 4096
- #endif
- #ifdef ENTT_PACKED_PAGE
- static_assert(ENTT_PACKED_PAGE && ((ENTT_PACKED_PAGE & (ENTT_PACKED_PAGE - 1)) == 0), "ENTT_PACKED_PAGE must be a power of two");
- #else
- # 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
- # include <type_traits>
- # define ENTT_IGNORE_IF_EMPTY std::false_type
- #else
- # include <type_traits>
- # define ENTT_IGNORE_IF_EMPTY std::true_type
- #endif
- #ifndef ENTT_STANDARD_CPP
- # 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
- #endif
- namespace entt {
- /*! @brief Identity function object (waiting for C++20). */
- struct identity {
- /**
- * @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;
- };
- }
- #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 "../config/config.h"
- // #include "../core/attribute.h"
- // #include "hashed_string.hpp"
- // #include "fwd.hpp"
- namespace entt {
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- namespace internal {
- struct ENTT_API type_seq 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;
- }
- }
- /**
- * 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_seq 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_seq::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_seq<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. */
- class type_info final {
- template<typename>
- friend type_info type_id() ENTT_NOEXCEPT;
- type_info(id_type seq_v, id_type hash_v, std::string_view name_v) ENTT_NOEXCEPT
- : seq_value{seq_v},
- hash_value{hash_v},
- name_value{name_v}
- {}
- public:
- /*! @brief Default constructor. */
- type_info() ENTT_NOEXCEPT
- : type_info({}, {}, {})
- {}
- /*! @brief Default copy constructor. */
- type_info(const type_info &) ENTT_NOEXCEPT = default;
- /*! @brief Default move constructor. */
- type_info(type_info &&) ENTT_NOEXCEPT = default;
- /**
- * @brief Default copy assignment operator.
- * @return This type info object.
- */
- type_info & operator=(const type_info &) ENTT_NOEXCEPT = default;
- /**
- * @brief Default move assignment operator.
- * @return This type info object.
- */
- type_info & operator=(type_info &&) ENTT_NOEXCEPT = default;
- /**
- * @brief Checks if a type info object is properly initialized.
- * @return True if the object is properly initialized, false otherwise.
- */
- [[nodiscard]] explicit operator bool() const ENTT_NOEXCEPT {
- return name_value.data() != nullptr;
- }
- /**
- * @brief Type sequential identifier.
- * @return Type sequential identifier.
- */
- [[nodiscard]] id_type seq() const ENTT_NOEXCEPT {
- return seq_value;
- }
- /**
- * @brief Type hash.
- * @return Type hash.
- */
- [[nodiscard]] id_type hash() const ENTT_NOEXCEPT {
- return hash_value;
- }
- /**
- * @brief Type name.
- * @return Type name.
- */
- [[nodiscard]] std::string_view name() const ENTT_NOEXCEPT {
- return name_value;
- }
- /**
- * @brief Compares the contents of two type info objects.
- * @param other Object with which to compare.
- * @return False if the two contents differ, true otherwise.
- */
- [[nodiscard]] bool operator==(const type_info &other) const ENTT_NOEXCEPT {
- return hash_value == other.hash_value;
- }
- private:
- id_type seq_value;
- id_type hash_value;
- std::string_view name_value;
- };
- /**
- * @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 contents differ, false otherwise.
- */
- [[nodiscard]] inline bool operator!=(const type_info &lhs, const type_info &rhs) ENTT_NOEXCEPT {
- return !(lhs == rhs);
- }
- /**
- * @brief Returns the type info object for a given type.
- * @tparam Type Type for which to generate a type info object.
- * @return The type info object for the given type.
- */
- template<typename Type>
- [[nodiscard]] type_info type_id() ENTT_NOEXCEPT {
- return type_info{
- type_seq<std::remove_cv_t<std::remove_reference_t<Type>>>::value(),
- type_hash<std::remove_cv_t<std::remove_reference_t<Type>>>::value(),
- type_name<std::remove_cv_t<std::remove_reference_t<Type>>>::value()
- };
- }
- }
- #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<class 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_t = 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_v = 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::disjunction_v<std::is_same<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<class 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;
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- namespace internal {
- template<typename>
- [[nodiscard]] constexpr bool is_equality_comparable(...) { return false; }
- template<typename Type>
- [[nodiscard]] constexpr auto is_equality_comparable(choice_t<0>)
- -> decltype(std::declval<Type>() == std::declval<Type>()) { return true; }
- template<typename Type>
- [[nodiscard]] constexpr auto is_equality_comparable(choice_t<1>)
- -> decltype(std::declval<typename Type::value_type>(), std::declval<Type>() == std::declval<Type>()) {
- if constexpr(std::is_same_v<typename Type::value_type, Type>) {
- return is_equality_comparable<Type>(choice<0>);
- } else {
- return is_equality_comparable<typename Type::value_type>(choice<2>);
- }
- }
- template<typename Type>
- [[nodiscard]] constexpr auto is_equality_comparable(choice_t<2>)
- -> decltype(std::declval<typename Type::mapped_type>(), std::declval<Type>() == std::declval<Type>()) {
- return is_equality_comparable<typename Type::key_type>(choice<2>) && is_equality_comparable<typename Type::mapped_type>(choice<2>);
- }
- }
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /**
- * @brief Provides the member constant `value` to true if a given type is
- * equality comparable, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_equality_comparable: std::bool_constant<internal::is_equality_comparable<Type>(choice<2>)> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<class Type>
- inline constexpr bool is_equality_comparable_v = is_equality_comparable<Type>::value;
- /*! @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 {};
- /*! @copydoc is_iterator */
- template<typename Type>
- struct is_iterator<Type, std::void_t<typename std::iterator_traits<Type>::iterator_category>>
- : std::true_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 of the
- * required iterator type, false otherwise.
- * @tparam Type The type to test.
- * @tparam It Required iterator type.
- */
- template<typename Type, typename It, typename = void>
- struct is_iterator_type: std::false_type {};
- /*! @copydoc is_iterator_type */
- template<typename Type, typename It>
- struct is_iterator_type<Type, It, std::enable_if_t<is_iterator_v<Type> && std::is_same_v<Type, It>>>
- : std::true_type
- {};
- /*! @copydoc is_iterator_type */
- template<typename Type, typename It>
- struct is_iterator_type<Type, It, std::enable_if_t<!std::is_same_v<Type, It>, std::void_t<typename It::iterator_type>>>
- : is_iterator_type<Type, typename It::iterator_type>
- {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- * @tparam It Required iterator type.
- */
- template<typename Type, typename It>
- inline constexpr bool is_iterator_type_v = is_iterator_type<Type, It>::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;
- }
- #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, DTOR, COMP, ADDR, CADDR, TYPE };
- 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 &, 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>
- [[nodiscard]] static constexpr policy type_to_policy() {
- if constexpr(std::is_lvalue_reference_v<Type>) {
- if constexpr(std::is_const_v<std::remove_reference_t<Type>>) {
- return policy::CREF;
- } else {
- return policy::REF;
- }
- } else {
- return policy::OWNER;
- }
- }
- template<typename Type>
- [[nodiscard]] static bool compare(const void *lhs, const void *rhs) {
- if constexpr(!std::is_function_v<Type> && is_equality_comparable_v<Type>) {
- return *static_cast<const Type *>(lhs) == *static_cast<const Type *>(rhs);
- } else {
- return lhs == rhs;
- }
- }
- template<typename Type>
- static const void * basic_vtable([[maybe_unused]] const operation op, [[maybe_unused]] const basic_any &from, [[maybe_unused]] void *to) {
- static_assert(std::is_same_v<std::remove_reference_t<std::remove_const_t<Type>>, Type>, "Invalid type");
- if constexpr(!std::is_void_v<Type>) {
- const Type *instance = (in_situ<Type> && from.mode == policy::OWNER)
- ? ENTT_LAUNDER(reinterpret_cast<const Type *>(&from.storage))
- : static_cast<const Type *>(from.instance);
- switch(op) {
- case operation::COPY:
- if constexpr(std::is_copy_constructible_v<Type>) {
- static_cast<basic_any *>(to)->emplace<Type>(*instance);
- }
- break;
- case operation::MOVE:
- if constexpr(in_situ<Type>) {
- if(from.mode == policy::OWNER) {
- return new (&static_cast<basic_any *>(to)->storage) Type{std::move(*const_cast<Type *>(instance))};
- }
- }
- return (static_cast<basic_any *>(to)->instance = std::exchange(const_cast<basic_any &>(from).instance, nullptr));
- case operation::DTOR:
- if(from.mode == policy::OWNER) {
- if constexpr(in_situ<Type>) {
- instance->~Type();
- } else if constexpr(std::is_array_v<Type>) {
- delete[] instance;
- } else {
- delete instance;
- }
- }
- break;
- case operation::COMP:
- return compare<Type>(instance, (*static_cast<const basic_any **>(to))->data()) ? to : nullptr;
- case operation::ADDR:
- if(from.mode == policy::CREF) {
- return nullptr;
- }
- [[fallthrough]];
- case operation::CADDR:
- return instance;
- case operation::TYPE:
- *static_cast<type_info *>(to) = type_id<Type>();
- break;
- }
- }
- return nullptr;
- }
- template<typename Type, typename... Args>
- void initialize([[maybe_unused]] Args &&... args) {
- if constexpr(!std::is_void_v<Type>) {
- if constexpr(std::is_lvalue_reference_v<Type>) {
- static_assert(sizeof...(Args) == 1u && (std::is_lvalue_reference_v<Args> && ...), "Invalid arguments");
- 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()},
- 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. */
- basic_any() ENTT_NOEXCEPT
- : instance{},
- vtable{&basic_vtable<void>},
- 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)
- : instance{},
- vtable{&basic_vtable<std::remove_const_t<std::remove_reference_t<Type>>>},
- mode{type_to_policy<Type>()}
- {
- initialize<Type>(std::forward<Args>(args)...);
- }
- /**
- * @brief Constructs a wrapper that holds an unmanaged object.
- * @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>
- basic_any(std::reference_wrapper<Type> value) ENTT_NOEXCEPT
- : basic_any{}
- {
- // invokes deprecated assignment operator (and avoids issues with vs2017)
- *this = value;
- }
- /**
- * @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)
- : instance{},
- vtable{&basic_vtable<std::decay_t<Type>>},
- mode{policy::OWNER}
- {
- 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)
- : instance{},
- vtable{&basic_vtable<void>},
- mode{policy::OWNER}
- {
- other.vtable(operation::COPY, other, this);
- }
- /**
- * @brief Move constructor.
- * @param other The instance to move from.
- */
- basic_any(basic_any &&other) ENTT_NOEXCEPT
- : instance{},
- vtable{other.vtable},
- mode{other.mode}
- {
- vtable(operation::MOVE, other, this);
- }
- /*! @brief Frees the internal storage, whatever it means. */
- ~basic_any() {
- vtable(operation::DTOR, *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();
- 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 {
- std::exchange(vtable, other.vtable)(operation::DTOR, *this, nullptr);
- other.vtable(operation::MOVE, other, this);
- 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>
- [[deprecated("Use std::in_place_type<T &>, entt::make_any<T &>, emplace<Type &> or forward_as_any instead")]]
- basic_any & operator=(std::reference_wrapper<Type> value) ENTT_NOEXCEPT {
- emplace<Type &>(value.get());
- 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 type of the contained object.
- * @return The type of the contained object, if any.
- */
- [[nodiscard]] type_info type() const ENTT_NOEXCEPT {
- type_info info{};
- vtable(operation::TYPE, *this, &info);
- 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(operation::CADDR, *this, nullptr);
- }
- /*! @copydoc data */
- [[nodiscard]] void * data() ENTT_NOEXCEPT {
- return const_cast<void *>(vtable(operation::ADDR, *this, 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) {
- std::exchange(vtable, &basic_vtable<std::remove_const_t<std::remove_reference_t<Type>>>)(operation::DTOR, *this, nullptr);
- mode = type_to_policy<Type>();
- initialize<Type>(std::forward<Args>(args)...);
- }
- /*! @brief Destroys contained object */
- void reset() {
- std::exchange(vtable, &basic_vtable<void>)(operation::DTOR, *this, 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(operation::CADDR, *this, nullptr) == 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 {
- const basic_any *trampoline = &other;
- return type() == other.type() && (vtable(operation::COMP, *this, &trampoline) || !other.data());
- }
- /**
- * @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; };
- 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 {
- // 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>(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 {
- return (data->type() == type_id<Type>() ? static_cast<const Type *>(data->data()) : nullptr);
- }
- /*! @copydoc any_cast */
- template<typename Type, std::size_t Len, std::size_t Align>
- Type * any_cast(basic_any<Len, Align> *data) ENTT_NOEXCEPT {
- // last attempt to make wrappers for const references return their values
- return (data->type() == type_id<Type>() ? static_cast<Type *>(static_cast<constness_as_t<basic_any<Len, Align>, Type> *>(data)->data()) : nullptr);
- }
- /**
- * @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)};
- }
- }
- #endif
- // #include "../core/fwd.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 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;
- };
- }
- #endif
- // #include "../core/type_info.hpp"
- // #include "../core/type_traits.hpp"
- // #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);
- }
- };
- }
- #endif
- // #include "ctx.hpp"
- #ifndef ENTT_META_CTX_HPP
- #define ENTT_META_CTX_HPP
- // #include "../core/attribute.h"
- // #include "../config/config.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;
- }
- };
- }
- /**
- * 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()};
- };
- }
- #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/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 {
- struct meta_type_node;
- struct meta_prop_node {
- meta_prop_node * next;
- const meta_any &id;
- meta_any &value;
- };
- struct meta_base_node {
- meta_type_node * const parent;
- meta_base_node * next;
- meta_type_node *(* const type)() ENTT_NOEXCEPT;
- const void *(* const cast)(const void *) ENTT_NOEXCEPT;
- };
- struct meta_conv_node {
- meta_type_node * const parent;
- meta_conv_node * next;
- meta_type_node *(* const type)() ENTT_NOEXCEPT;
- meta_any(* const conv)(const void *);
- };
- struct meta_ctor_node {
- using size_type = std::size_t;
- meta_type_node * const parent;
- meta_ctor_node * next;
- meta_prop_node * prop;
- const size_type arity;
- meta_type(* const arg)(const size_type) ENTT_NOEXCEPT;
- meta_any(* const invoke)(meta_any * const);
- };
- struct meta_data_node {
- id_type id;
- meta_type_node * const parent;
- meta_data_node * next;
- meta_prop_node * prop;
- const bool is_const;
- const bool is_static;
- meta_type_node *(* const 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;
- meta_type_node * const parent;
- meta_func_node * next;
- meta_prop_node * prop;
- const size_type arity;
- const bool is_const;
- const bool is_static;
- meta_type_node *(* const ret)() ENTT_NOEXCEPT;
- meta_type(* const arg)(const size_type) ENTT_NOEXCEPT;
- meta_any(* const invoke)(meta_handle, meta_any *);
- };
- struct meta_template_info {
- using size_type = std::size_t;
- const bool is_template_specialization;
- const size_type arity;
- meta_type_node *(* const type)() ENTT_NOEXCEPT;
- 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;
- meta_type_node * next;
- meta_prop_node * prop;
- const size_type size_of;
- const bool is_void;
- const bool is_integral;
- const bool is_floating_point;
- const bool is_array;
- const bool is_enum;
- const bool is_union;
- const bool is_class;
- const bool is_pointer;
- const bool is_function_pointer;
- const bool is_member_object_pointer;
- const bool is_member_function_pointer;
- const bool is_pointer_like;
- const bool is_sequence_container;
- const bool is_associative_container;
- const meta_template_info template_info;
- const size_type rank;
- size_type(* const extent)(const size_type) ENTT_NOEXCEPT ;
- meta_type_node *(* const remove_pointer)() ENTT_NOEXCEPT;
- meta_type_node *(* const remove_extent)() ENTT_NOEXCEPT;
- meta_ctor_node * const def_ctor;
- 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<auto Member, typename Op, typename Node>
- auto meta_visit(const Op &op, const Node *node)
- -> std::decay_t<decltype(node->*Member)> {
- for(auto *curr = node->*Member; curr; curr = curr->next) {
- if(op(curr)) {
- return curr;
- }
- }
- if constexpr(std::is_same_v<Node, meta_type_node>) {
- for(auto *curr = node->base; curr; curr = curr->next) {
- if(auto *ret = meta_visit<Member>(op, curr->type()); ret) {
- return ret;
- }
- }
- }
- return 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");
- template<std::size_t... Index>
- [[nodiscard]] static auto extent(const meta_type_node::size_type dim, std::index_sequence<Index...>) ENTT_NOEXCEPT {
- meta_type_node::size_type ext{};
- ((ext = (dim == Index ? std::extent_v<Type, Index> : ext)), ...);
- return ext;
- }
- [[nodiscard]] static meta_ctor_node * meta_default_constructor([[maybe_unused]] meta_type_node *type) ENTT_NOEXCEPT {
- if constexpr(std::is_default_constructible_v<Type>) {
- static meta_ctor_node node{
- type,
- nullptr,
- nullptr,
- 0u,
- nullptr,
- [](meta_any * const) { return meta_any{std::in_place_type<Type>}; }
- };
- return &node;
- } else {
- return nullptr;
- }
- }
- [[nodiscard]] static meta_template_info meta_template_descriptor() ENTT_NOEXCEPT {
- if constexpr(is_complete_v<meta_template_traits<Type>>) {
- return {
- true,
- 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);
- }
- };
- } else {
- return { false, 0u, nullptr, nullptr };
- }
- }
- public:
- [[nodiscard]] static meta_type_node * resolve() ENTT_NOEXCEPT {
- static meta_type_node node{
- type_id<Type>(),
- {},
- nullptr,
- nullptr,
- size_of_v<Type>,
- std::is_void_v<Type>,
- std::is_integral_v<Type>,
- std::is_floating_point_v<Type>,
- std::is_array_v<Type>,
- std::is_enum_v<Type>,
- std::is_union_v<Type>,
- std::is_class_v<Type>,
- std::is_pointer_v<Type>,
- std::is_pointer_v<Type> && std::is_function_v<std::remove_pointer_t<Type>>,
- std::is_member_object_pointer_v<Type>,
- std::is_member_function_pointer_v<Type>,
- is_meta_pointer_like_v<Type>,
- is_complete_v<meta_sequence_container_traits<Type>>,
- is_complete_v<meta_associative_container_traits<Type>>,
- meta_template_descriptor(),
- std::rank_v<Type>,
- [](meta_type_node::size_type dim) ENTT_NOEXCEPT { return extent(dim, std::make_index_sequence<std::rank_v<Type>>{}); },
- &meta_node<std::remove_cv_t<std::remove_reference_t<std::remove_pointer_t<Type>>>>::resolve,
- &meta_node<std::remove_cv_t<std::remove_reference_t<std::remove_extent_t<Type>>>>::resolve,
- meta_default_constructor(&node),
- meta_default_constructor(&node)
- };
- return &node;
- }
- };
- template<typename Type>
- struct meta_info: meta_node<std::remove_cv_t<std::remove_reference_t<Type>>> {};
- template<typename... Args>
- 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_info<Args>::resolve()...};
- return args[index + 1u];
- }
- }
- /**
- * Internal details not to be documented.
- * @endcond
- */
- }
- #endif
- // #include "range.hpp"
- #ifndef ENTT_META_RANGE_HPP
- #define ENTT_META_RANGE_HPP
- #include <cstddef>
- #include <iterator>
- namespace entt {
- /**
- * @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>
- class meta_range {
- struct range_iterator {
- using difference_type = std::ptrdiff_t;
- using value_type = Type;
- using pointer = void;
- using reference = value_type;
- using iterator_category = std::input_iterator_tag;
- using node_type = Node;
- range_iterator() ENTT_NOEXCEPT = default;
- range_iterator(node_type *head) ENTT_NOEXCEPT
- : it{head}
- {}
- range_iterator & operator++() ENTT_NOEXCEPT {
- return (it = it->next), *this;
- }
- range_iterator operator++(int) ENTT_NOEXCEPT {
- range_iterator orig = *this;
- return ++(*this), orig;
- }
- [[nodiscard]] reference operator*() const ENTT_NOEXCEPT {
- return it;
- }
- [[nodiscard]] bool operator==(const range_iterator &other) const ENTT_NOEXCEPT {
- return other.it == it;
- }
- [[nodiscard]] bool operator!=(const range_iterator &other) const ENTT_NOEXCEPT {
- return !(*this == other);
- }
- private:
- node_type *it{};
- };
- public:
- /*! @brief Node type. */
- using node_type = Node;
- /*! @brief Input iterator type. */
- using iterator = range_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)
- : node{head}
- {}
- /**
- * @brief Returns an iterator to the beginning.
- * @return An iterator to the first meta object of the range.
- */
- [[nodiscard]] iterator begin() const ENTT_NOEXCEPT {
- return iterator{node};
- }
- /**
- * @brief Returns an iterator to the end.
- * @return An iterator to the element following the last meta object of the
- * range.
- */
- [[nodiscard]] iterator end() const ENTT_NOEXCEPT {
- return iterator{};
- }
- private:
- node_type *node{nullptr};
- };
- }
- #endif
- // #include "type_traits.hpp"
- namespace entt {
- class meta_any;
- class meta_type;
- /*! @brief Proxy object for sequence containers. */
- class meta_sequence_container {
- template<typename>
- struct meta_sequence_container_proxy;
- 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_fn{&meta_sequence_container_proxy<Type>::value_type},
- size_fn{&meta_sequence_container_proxy<Type>::size},
- resize_fn{&meta_sequence_container_proxy<Type>::resize},
- clear_fn{&meta_sequence_container_proxy<Type>::clear},
- begin_fn{&meta_sequence_container_proxy<Type>::begin},
- end_fn{&meta_sequence_container_proxy<Type>::end},
- insert_fn{&meta_sequence_container_proxy<Type>::insert},
- erase_fn{&meta_sequence_container_proxy<Type>::erase},
- get_fn{&meta_sequence_container_proxy<Type>::get},
- storage{std::move(instance)}
- {}
- [[nodiscard]] inline meta_type value_type() const ENTT_NOEXCEPT;
- [[nodiscard]] inline size_type size() const ENTT_NOEXCEPT;
- inline bool resize(size_type);
- inline bool clear();
- [[nodiscard]] inline iterator begin();
- [[nodiscard]] inline iterator end();
- inline std::pair<iterator, bool> insert(iterator, meta_any);
- inline std::pair<iterator, bool> erase(iterator);
- [[nodiscard]] inline meta_any operator[](size_type);
- [[nodiscard]] inline explicit operator bool() const ENTT_NOEXCEPT;
- private:
- meta_type(* value_type_fn)() ENTT_NOEXCEPT = nullptr;
- size_type(* size_fn)(const any &) ENTT_NOEXCEPT = nullptr;
- bool(* resize_fn)(any &, size_type) = nullptr;
- bool(* clear_fn)(any &) = nullptr;
- iterator(* begin_fn)(any &) = nullptr;
- iterator(* end_fn)(any &) = nullptr;
- std::pair<iterator, bool>(* insert_fn)(any &, iterator, meta_any &) = nullptr;
- std::pair<iterator, bool>(* erase_fn)(any &, iterator) = nullptr;
- meta_any(* get_fn)(any &, size_type) = nullptr;
- any storage{};
- };
- /*! @brief Proxy object for associative containers. */
- class meta_associative_container {
- template<typename>
- struct meta_associative_container_proxy;
- 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{is_key_only_meta_associative_container_v<Type>},
- key_type_fn{&meta_associative_container_proxy<Type>::key_type},
- mapped_type_fn{&meta_associative_container_proxy<Type>::mapped_type},
- value_type_fn{&meta_associative_container_proxy<Type>::value_type},
- size_fn{&meta_associative_container_proxy<Type>::size},
- clear_fn{&meta_associative_container_proxy<Type>::clear},
- begin_fn{&meta_associative_container_proxy<Type>::begin},
- end_fn{&meta_associative_container_proxy<Type>::end},
- insert_fn{&meta_associative_container_proxy<Type>::insert},
- erase_fn{&meta_associative_container_proxy<Type>::erase},
- find_fn{&meta_associative_container_proxy<Type>::find},
- storage{std::move(instance)}
- {}
- [[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{};
- meta_type(* key_type_fn)() ENTT_NOEXCEPT = nullptr;
- meta_type(* mapped_type_fn)() ENTT_NOEXCEPT = nullptr;
- meta_type(* value_type_fn)() ENTT_NOEXCEPT = nullptr;
- size_type(* size_fn)(const any &) ENTT_NOEXCEPT = nullptr;
- bool(* clear_fn)(any &) = nullptr;
- iterator(* begin_fn)(any &) = nullptr;
- iterator(* end_fn)(any &) = 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 { DTOR, 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 &from, [[maybe_unused]] void *to) {
- static_assert(std::is_same_v<std::remove_reference_t<std::remove_const_t<Type>>, Type>, "Invalid type");
- if constexpr(!std::is_void_v<Type>) {
- switch(op) {
- case operation::DTOR:
- if(auto *curr = static_cast<internal::meta_type_node *>(to); curr->dtor && from.owner()) {
- curr->dtor(const_cast<any &>(from).data());
- }
- break;
- case operation::DEREF:
- if constexpr(is_meta_pointer_like_v<Type>) {
- using element_type = std::remove_const_t<typename std::pointer_traits<Type>::element_type>;
- if constexpr(std::is_function_v<element_type>) {
- *static_cast<meta_any *>(to) = any_cast<Type>(from);
- } 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 &>(from)));
- static_cast<meta_any *>(to)->emplace<in_place_type>(adl_meta_pointer_like<Type>::dereference(any_cast<const Type &>(from)));
- }
- }
- case operation::SEQ:
- if constexpr(is_complete_v<meta_sequence_container_traits<Type>>) {
- *static_cast<meta_sequence_container *>(to) = { std::in_place_type<Type>, std::move(const_cast<any &>(from)) };
- }
- break;
- case operation::ASSOC:
- if constexpr(is_complete_v<meta_associative_container_traits<Type>>) {
- *static_cast<meta_associative_container *>(to) = { std::in_place_type<Type>, std::move(const_cast<any &>(from)) };
- }
- break;
- }
- }
- }
- 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_info<Type>::resolve()},
- vtable{&basic_vtable<std::remove_const_t<std::remove_reference_t<Type>>>}
- {}
- /**
- * @brief Constructs a wrapper that holds an unmanaged object.
- * @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>
- meta_any(std::reference_wrapper<Type> value)
- : meta_any{}
- {
- // invokes deprecated assignment operator (and avoids issues with vs2017)
- *this = value;
- }
- /**
- * @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)
- : storage{std::forward<Type>(value)},
- node{internal::meta_info<std::decay_t<Type>>::resolve()},
- vtable{&basic_vtable<std::decay_t<Type>>}
- {}
- /**
- * @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() {
- vtable(operation::DTOR, storage, node);
- }
- /**
- * @brief Copy assignment operator.
- * @param other The instance to copy from.
- * @return This meta any object.
- */
- meta_any & operator=(const meta_any &other) {
- std::exchange(vtable, other.vtable)(operation::DTOR, storage, node);
- 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 {
- std::exchange(vtable, std::exchange(other.vtable, &basic_vtable<void>))(operation::DTOR, storage, node);
- 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>
- [[deprecated("Use std::in_place_type<T &>, entt::make_meta<T &>, emplace<Type &> or forward_as_meta instead")]]
- meta_any & operator=(std::reference_wrapper<Type> value) {
- emplace<Type &>(value.get());
- 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;
- }
- /**
- * @brief Returns the type of the underlying object.
- * @return The type of the underlying object, if any.
- */
- [[nodiscard]] inline meta_type type() const ENTT_NOEXCEPT;
- /**
- * @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 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 must be 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(node) {
- if(const auto info = type_id<Type>(); node->info == info) {
- return any_cast<Type>(&storage);
- } else if(const auto *base = internal::meta_visit<&internal::meta_type_node::base>([info](const auto *curr) { return curr->type()->info == info; }, node); base) {
- return static_cast<const Type *>(base->cast(storage.data()));
- }
- }
- return nullptr;
- }
- /*! @copydoc try_cast */
- template<typename Type>
- [[nodiscard]] Type * try_cast() {
- if(node) {
- if(const auto info = type_id<Type>(); node->info == info) {
- return any_cast<Type>(&storage);
- } else if(const auto *base = internal::meta_visit<&internal::meta_type_node::base>([info](const auto *curr) { return curr->type()->info == info; }, node); base) {
- return static_cast<Type *>(const_cast<constness_as_t<void, Type> *>(base->cast(static_cast<constness_as_t<any, Type> &>(storage).data())));
- }
- }
- 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 in 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.
- * @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 {
- if(try_cast<std::remove_reference_t<Type>>() != nullptr) {
- return as_ref();
- } else if(node) {
- if(const auto * const conv = internal::meta_visit<&internal::meta_type_node::conv>([info = type_id<Type>()](const auto *curr) { return curr->type()->info == info; }, node); conv) {
- return conv->conv(storage.data());
- }
- }
- return {};
- }
- /**
- * @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() {
- // forces const on non-reference types to make them work also with wrappers for const references
- if(try_cast<std::remove_reference_t<const Type>>() != nullptr) {
- return true;
- } else if(node) {
- if(const auto * const conv = internal::meta_visit<&internal::meta_type_node::conv>([info = type_id<Type>()](const auto *curr) { return curr->type()->info == info; }, node); conv) {
- *this = conv->conv(std::as_const(storage).data());
- return true;
- }
- }
- return false;
- }
- /**
- * @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) {
- std::exchange(vtable, &basic_vtable<std::remove_const_t<std::remove_reference_t<Type>>>)(operation::DTOR, storage, node);
- storage.emplace<Type>(std::forward<Args>(args)...);
- node = internal::meta_info<Type>::resolve();
- }
- /*! @brief Destroys contained object */
- void reset() {
- std::exchange(vtable, &basic_vtable<void>)(operation::DTOR, storage, node);
- 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 {
- meta_sequence_container proxy;
- vtable(operation::SEQ, storage.as_ref(), &proxy);
- return proxy;
- }
- /*! @copydoc as_sequence_container */
- [[nodiscard]] meta_sequence_container as_sequence_container() const ENTT_NOEXCEPT {
- meta_sequence_container proxy;
- vtable(operation::SEQ, storage.as_ref(), &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 {
- meta_associative_container proxy;
- vtable(operation::ASSOC, storage.as_ref(), &proxy);
- return proxy;
- }
- /*! @copydoc as_associative_container */
- [[nodiscard]] meta_associative_container as_associative_container() const ENTT_NOEXCEPT {
- meta_associative_container proxy;
- vtable(operation::ASSOC, storage.as_ref(), &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);
- }
- /**
- * @brief Checks if two wrappers differ in their content.
- * @param other Wrapper with which to compare.
- * @return False if the two objects differ in their content, true otherwise.
- */
- [[nodiscard]] bool operator==(const meta_any &other) const {
- return (!node && !other.node) || (node && other.node && node->info == other.node->info && storage == other.storage);
- }
- /**
- * @brief Aliasing constructor.
- * @return A wrapper that shares a reference to an unmanaged object.
- */
- [[nodiscard]] meta_any as_ref() ENTT_NOEXCEPT {
- return meta_any{*this, storage.as_ref()};
- }
- /*! @copydoc as_ref */
- [[nodiscard]] meta_any as_ref() const ENTT_NOEXCEPT {
- return meta_any{*this, storage.as_ref()};
- }
- 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 constructors. */
- struct meta_ctor {
- /*! @brief Node type. */
- using node_type = internal::meta_ctor_node;
- /*! @brief Unsigned integer type. */
- using size_type = typename node_type::size_type;
- /*! @copydoc meta_prop::meta_prop */
- meta_ctor(const node_type *curr = nullptr) ENTT_NOEXCEPT
- : node{curr}
- {}
- /**
- * @brief Returns the type to which an object belongs.
- * @return The type to which the object belongs.
- */
- [[nodiscard]] inline meta_type parent() const ENTT_NOEXCEPT;
- /**
- * @brief Returns the number of arguments accepted by a constructor.
- * @return The number of arguments accepted by the constructor.
- */
- [[nodiscard]] size_type arity() const ENTT_NOEXCEPT {
- return node->arity;
- }
- /**
- * @brief Returns the type of the i-th argument of a constructor.
- * @param index Index of the argument of which to return the type.
- * @return The type of the i-th argument of a constructor.
- */
- [[nodiscard]] meta_type arg(size_type index) const ENTT_NOEXCEPT;
- /**
- * @brief Creates an instance of the underlying type, if possible.
- *
- * Parameters must be such that a cast or conversion to the required types
- * is possible. Otherwise, an empty and thus invalid wrapper is returned.
- *
- * @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 invoke(meta_any * const args, const size_type sz) const {
- return sz == arity() ? node->invoke(args) : meta_any{};
- }
- /**
- * @copybrief invoke
- *
- * @sa invoke
- *
- * @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 invoke([[maybe_unused]] Args &&... args) const {
- meta_any arguments[sizeof...(Args) + 1u]{std::forward<Args>(args)...};
- return invoke(arguments, sizeof...(Args));
- }
- /**
- * @brief Returns a range to use to visit all properties.
- * @return An iterable range to use to visit all properties.
- */
- [[nodiscard]] meta_range<meta_prop> prop() const ENTT_NOEXCEPT {
- return node->prop;
- }
- /**
- * @brief Returns the property associated with a given key.
- * @param key The key to use to search for a property.
- * @return The property associated with the given key, if any.
- */
- [[nodiscard]] meta_prop prop(meta_any key) const {
- return internal::meta_visit<&node_type::prop>([&key](const auto *curr) { return curr->id == 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);
- }
- private:
- const node_type *node;
- };
- /*! @brief Opaque wrapper for data members. */
- struct meta_data {
- /*! @brief Node type. */
- using node_type = internal::meta_data_node;
- /*! @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;
- }
- /*! @copydoc meta_ctor::parent */
- [[nodiscard]] inline meta_type parent() const ENTT_NOEXCEPT;
- /**
- * @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->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->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. Otherwise, invoking the setter results in an undefined
- * behavior.<br/>
- * The type of the value must be 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. Otherwise, invoking the getter results in an undefined behavior.
- *
- * @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));
- }
- /*! @copydoc meta_ctor::prop */
- [[nodiscard]] meta_range<meta_prop> prop() const ENTT_NOEXCEPT {
- return node->prop;
- }
- /**
- * @brief Returns the property associated with a given key.
- * @param key The key to use to search for a property.
- * @return The property associated with the given key, if any.
- */
- [[nodiscard]] meta_prop prop(meta_any key) const {
- return internal::meta_visit<&node_type::prop>([&key](const auto *curr) { return curr->id == 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);
- }
- 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;
- }
- /*! @copydoc meta_ctor::parent */
- [[nodiscard]] inline meta_type parent() const ENTT_NOEXCEPT;
- /**
- * @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->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->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(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. Otherwise, invoking the underlying function results in an
- * undefined behavior.
- *
- * @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_ctor::prop */
- [[nodiscard]] meta_range<meta_prop> prop() const ENTT_NOEXCEPT {
- return node->prop;
- }
- /**
- * @brief Returns the property associated with a given key.
- * @param key The key to use to search for a property.
- * @return The property associated with the given key, if any.
- */
- [[nodiscard]] meta_prop prop(meta_any key) const {
- return internal::meta_visit<&node_type::prop>([&key](const auto *curr) { return curr->id == 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);
- }
- private:
- const node_type *node;
- };
- /*! @brief Opaque wrapper for types. */
- class meta_type {
- static bool can_cast_or_convert(const internal::meta_type_node *type, const type_info info) ENTT_NOEXCEPT {
- if(type->info == info) {
- return true;
- }
- for(const auto *curr = type->conv; curr; curr = curr->next) {
- if(curr->type()->info == info) {
- return true;
- }
- }
- for(const auto *curr = type->base; curr; curr = curr->next) {
- if(auto *target = curr->type(); can_cast_or_convert(target, info)) {
- return true;
- }
- }
- return false;
- }
- template<typename... Args, auto... Index>
- [[nodiscard]] static const internal::meta_ctor_node * ctor(const internal::meta_ctor_node *curr, std::index_sequence<Index...>) {
- for(; curr; curr = curr->next) {
- if(curr->arity == sizeof...(Args) && (can_cast_or_convert(internal::meta_info<Args>::resolve(), curr->arg(Index).info()) && ...)) {
- return curr;
- }
- }
- return nullptr;
- }
- template<auto... Member, typename Node>
- void unregister_all(Node **curr) {
- while(*curr) {
- (unregister_all(&((*curr)->*Member)), ...);
- *curr = std::exchange((*curr)->next, nullptr);
- }
- }
- 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(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(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]] 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 void or not.
- * @return True if the underlying type is void, false otherwise.
- */
- [[nodiscard]] bool is_void() const ENTT_NOEXCEPT {
- return node->is_void;
- }
- /**
- * @brief Checks whether a type refers to an integral type or not.
- * @return True if the underlying type is an integral type, false otherwise.
- */
- [[nodiscard]] bool is_integral() const ENTT_NOEXCEPT {
- return node->is_integral;
- }
- /**
- * @brief Checks whether a type refers to a floating-point type or not.
- * @return True if the underlying type is a floating-point type, false
- * otherwise.
- */
- [[nodiscard]] bool is_floating_point() const ENTT_NOEXCEPT {
- return node->is_floating_point;
- }
- /**
- * @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->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->is_enum;
- }
- /**
- * @brief Checks whether a type refers to an union or not.
- * @return True if the underlying type is an union, false otherwise.
- */
- [[nodiscard]] bool is_union() const ENTT_NOEXCEPT {
- return node->is_union;
- }
- /**
- * @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->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->is_pointer;
- }
- /**
- * @brief Checks whether a type refers to a function pointer or not.
- * @return True if the underlying type is a function pointer, false
- * otherwise.
- */
- [[nodiscard]] bool is_function_pointer() const ENTT_NOEXCEPT {
- return node->is_function_pointer;
- }
- /**
- * @brief Checks whether a type refers to a pointer to data member or not.
- * @return True if the underlying type is a pointer to data member, false
- * otherwise.
- */
- [[nodiscard]] bool is_member_object_pointer() const ENTT_NOEXCEPT {
- return node->is_member_object_pointer;
- }
- /**
- * @brief Checks whether a type refers to a pointer to member function or
- * not.
- * @return True if the underlying type is a pointer to member function,
- * false otherwise.
- */
- [[nodiscard]] bool is_member_function_pointer() const ENTT_NOEXCEPT {
- return node->is_member_function_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->is_pointer_like;
- }
- /**
- * @brief Checks whether a type refers to a sequence container or not.
- * @return True if the type is a sequence container, false otherwise.
- */
- [[nodiscard]] bool is_sequence_container() const ENTT_NOEXCEPT {
- return node->is_sequence_container;
- }
- /**
- * @brief Checks whether a type refers to an associative container or not.
- * @return True if the type is an associative container, false otherwise.
- */
- [[nodiscard]] bool is_associative_container() const ENTT_NOEXCEPT {
- return node->is_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->template_info.is_template_specialization;
- }
- /**
- * @brief Returns the number of template arguments, if any.
- * @return The number of template arguments, if any.
- */
- [[nodiscard]] size_type template_arity() const ENTT_NOEXCEPT {
- return node->template_info.arity;
- }
- /**
- * @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 is_template_specialization() ? node->template_info.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(size_type index) const ENTT_NOEXCEPT {
- return index < template_arity() ? node->template_info.arg(index) : meta_type{};
- }
- /**
- * @brief Provides the number of dimensions of an array type.
- * @return The number of dimensions in case of array types, 0 otherwise.
- */
- [[nodiscard]] size_type rank() const ENTT_NOEXCEPT {
- return node->rank;
- }
- /**
- * @brief The number of elements along the given dimension of an array type.
- * @param dim The dimension of which to return the number of elements.
- * @return The number of elements along the given dimension in case of array
- * types, 0 otherwise.
- */
- [[nodiscard]] size_type extent(size_type dim = {}) const ENTT_NOEXCEPT {
- return node->extent(dim);
- }
- /**
- * @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 Provides the type for which the array is defined.
- * @return The type for which the array is defined or this type if it
- * doesn't refer to an array type.
- */
- [[nodiscard]] meta_type remove_extent() const ENTT_NOEXCEPT {
- return node->remove_extent();
- }
- /**
- * @brief Returns a range to use to visit top-level base meta types.
- * @return An iterable range to use to visit top-level base meta types.
- */
- [[nodiscard]] meta_range<meta_type, internal::meta_base_node> base() const ENTT_NOEXCEPT {
- return node->base;
- }
- /**
- * @brief Returns the base meta type associated with a given identifier.
- * @param id Unique identifier.
- * @return The base meta type associated with the given identifier, if any.
- */
- [[nodiscard]] meta_type base(const id_type id) const {
- return internal::meta_visit<&node_type::base>([id](const auto *curr) { return curr->type()->id == id; }, node);
- }
- /**
- * @brief Returns a range to use to visit top-level constructors.
- * @return An iterable range to use to visit top-level constructors.
- */
- [[nodiscard]] meta_range<meta_ctor> ctor() const ENTT_NOEXCEPT {
- return node->ctor;
- }
- /**
- * @brief Returns a constructor for a given list of types of arguments.
- * @tparam Args Constructor arguments.
- * @return The requested constructor, if any.
- */
- template<typename... Args>
- [[nodiscard]] meta_ctor ctor() const {
- return ctor<Args...>(node->ctor, std::make_index_sequence<sizeof...(Args)>{});
- }
- /**
- * @brief Returns a range to use to visit top-level data.
- * @return An iterable range to use to visit top-level data.
- */
- [[nodiscard]] meta_range<meta_data> data() const ENTT_NOEXCEPT {
- return node->data;
- }
- /**
- * @brief Returns the data associated with a given identifier.
- *
- * The data of the base classes will also be visited, if any.
- *
- * @param id Unique identifier.
- * @return The data associated with the given identifier, if any.
- */
- [[nodiscard]] meta_data data(const id_type id) const {
- return internal::meta_visit<&node_type::data>([id](const auto *curr) { return curr->id == id; }, node);
- }
- /**
- * @brief Returns a range to use to visit top-level functions.
- * @return An iterable range to use to visit top-level functions.
- */
- [[nodiscard]] meta_range<meta_func> func() const ENTT_NOEXCEPT {
- return node->func;
- }
- /**
- * @brief Returns the function associated with a given identifier.
- *
- * The functions of the base classes will also be visited, if any.<br/>
- * In the case of overloaded functions, the first one with the required
- * identifier will be returned.
- *
- * @param id Unique identifier.
- * @return The function associated with the given identifier, if any.
- */
- [[nodiscard]] meta_func func(const id_type id) const {
- return internal::meta_visit<&node_type::func>([id](const auto *curr) { return curr->id == id; }, node);
- }
- /**
- * @brief Creates an instance of the underlying type, if possible.
- *
- * Parameters must be such that a cast or conversion to the required types
- * is possible. Otherwise, an empty and thus invalid wrapper is returned.
- *
- * @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 {
- meta_any ret{};
- internal::meta_visit<&node_type::ctor>([args, sz, &ret](const auto *curr) { return (curr->arity == sz) && (ret = curr->invoke(args)); }, node);
- return ret;
- }
- /**
- * @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. Otherwise, invoking the underlying function results in an
- * undefined behavior.
- *
- * @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 internal::meta_func_node* candidate{};
- size_type extent{sz + 1u};
- bool ambiguous{};
- for(auto *it = internal::meta_visit<&node_type::func>([id, sz](const auto *curr) { return curr->id == id && curr->arity == sz; }, node); it && it->id == id && it->arity == sz; it = it->next) {
- size_type direct{};
- size_type ext{};
- for(size_type next{}; next < sz && next == (direct + ext); ++next) {
- const auto type = args[next].type();
- const auto req = it->arg(next).info();
- type.info() == req ? ++direct : (ext += can_cast_or_convert(type.node, req));
- }
- if((direct + ext) == sz) {
- if(ext < extent) {
- candidate = it;
- extent = ext;
- ambiguous = false;
- } else if(ext == extent) {
- ambiguous = true;
- }
- }
- }
- return (candidate && !ambiguous) ? 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. Otherwise, invoking the setter results in an undefined
- * behavior.<br/>
- * The type of the value must be 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. Otherwise, invoking the getter results in an undefined behavior.
- *
- * @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 use to visit top-level properties.
- * @return An iterable range to use to visit top-level properties.
- */
- [[nodiscard]] meta_range<meta_prop> prop() const ENTT_NOEXCEPT {
- return node->prop;
- }
- /**
- * @brief Returns the property associated with a given key.
- *
- * Properties of the base classes will also be visited, if any.
- *
- * @param key The key to use to search for a property.
- * @return The property associated with the given key, if any.
- */
- [[nodiscard]] meta_prop prop(meta_any key) const {
- return internal::meta_visit<&node_type::prop>([&key](const auto *curr) { return curr->id == 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);
- }
- /**
- * @brief Resets a type and all its parts.
- *
- * This function 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.
- */
- void reset() ENTT_NOEXCEPT {
- for(auto** it = internal::meta_context::global(); *it; it = &(*it)->next) {
- if(*it == node) {
- *it = (*it)->next;
- break;
- }
- }
- unregister_all(&node->prop);
- unregister_all(&node->base);
- unregister_all(&node->conv);
- unregister_all<&internal::meta_ctor_node::prop>(&node->ctor);
- unregister_all<&internal::meta_data_node::prop>(&node->data);
- unregister_all<&internal::meta_func_node::prop>(&node->func);
- node->id = {};
- node->ctor = node->def_ctor;
- node->dtor = nullptr;
- }
- private:
- 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_type meta_ctor::parent() const ENTT_NOEXCEPT {
- return node->parent;
- }
- [[nodiscard]] inline meta_type meta_ctor::arg(size_type index) const ENTT_NOEXCEPT {
- return index < arity() ? node->arg(index) : meta_type{};
- }
- [[nodiscard]] inline meta_type meta_data::parent() const ENTT_NOEXCEPT {
- return node->parent;
- }
- [[nodiscard]] inline meta_type meta_data::type() const ENTT_NOEXCEPT {
- return node->type();
- }
- [[nodiscard]] inline meta_type meta_func::parent() const ENTT_NOEXCEPT {
- return node->parent;
- }
- [[nodiscard]] inline meta_type meta_func::ret() const ENTT_NOEXCEPT {
- return node->ret();
- }
- [[nodiscard]] inline meta_type meta_func::arg(size_type index) const ENTT_NOEXCEPT {
- return index < arity() ? node->arg(index) : meta_type{};
- }
- /*! @brief Opaque iterator for sequence containers. */
- class meta_sequence_container::meta_iterator {
- /*! @brief A sequence container can access the underlying iterator. */
- friend class meta_sequence_container;
- enum class operation { INCR, DEREF };
- using vtable_type = void(const operation, const any &, void *);
- template<typename It>
- static void basic_vtable(const operation op, const any &from, void *to) {
- switch(op) {
- case operation::INCR:
- ++any_cast<It &>(const_cast<any &>(from));
- break;
- case operation::DEREF:
- static_cast<meta_any *>(to)->emplace<typename std::iterator_traits<It>::reference>(*any_cast<const It &>(from));
- break;
- }
- }
- public:
- /*! @brief Signed integer type. */
- using difference_type = std::ptrdiff_t;
- /*! @brief Type of elements returned by the iterator. */
- using value_type = meta_any;
- /*! @brief Pointer type, `void` on purpose. */
- using pointer = void;
- /*! @brief Reference type, it is **not** an actual reference. */
- using reference = value_type;
- /*! @brief Iterator category. */
- using iterator_category = std::input_iterator_tag;
- /*! @brief Default constructor. */
- meta_iterator() ENTT_NOEXCEPT = default;
- /**
- * @brief Constructs a meta iterator from a given iterator.
- * @tparam It Type of actual iterator with which to build the meta iterator.
- * @param iter The actual iterator with which to build the meta iterator.
- */
- template<typename It>
- meta_iterator(It iter)
- : vtable{&basic_vtable<It>},
- handle{std::move(iter)}
- {}
- /*! @brief Pre-increment operator. @return This iterator. */
- meta_iterator & operator++() ENTT_NOEXCEPT {
- return vtable(operation::INCR, handle, nullptr), *this;
- }
- /*! @brief Post-increment operator. @return This iterator. */
- meta_iterator operator++(int) ENTT_NOEXCEPT {
- meta_iterator orig = *this;
- return ++(*this), orig;
- }
- /**
- * @brief Checks if two iterators refer to the same element.
- * @param other The iterator with which to compare.
- * @return True if the iterators refer to the same element, false otherwise.
- */
- [[nodiscard]] bool operator==(const meta_iterator &other) const ENTT_NOEXCEPT {
- return handle == other.handle;
- }
- /**
- * @brief Checks if two iterators refer to the same element.
- * @param other The iterator with which to compare.
- * @return False if the iterators refer to the same element, true otherwise.
- */
- [[nodiscard]] bool operator!=(const meta_iterator &other) const ENTT_NOEXCEPT {
- return !(*this == other);
- }
- /**
- * @brief Indirection operator.
- * @return The element to which the iterator points.
- */
- [[nodiscard]] reference operator*() const {
- meta_any other;
- vtable(operation::DEREF, handle, &other);
- return other;
- }
- /**
- * @brief Returns false if an iterator is invalid, true otherwise.
- * @return False if the iterator is invalid, true otherwise.
- */
- [[nodiscard]] explicit operator bool() const ENTT_NOEXCEPT {
- return static_cast<bool>(handle);
- }
- private:
- vtable_type *vtable{};
- any handle{};
- };
- template<typename Type>
- struct meta_sequence_container::meta_sequence_container_proxy {
- using traits_type = meta_sequence_container_traits<Type>;
- [[nodiscard]] static meta_type value_type() ENTT_NOEXCEPT {
- return internal::meta_info<typename Type::value_type>::resolve();
- }
- [[nodiscard]] static size_type size(const any &container) ENTT_NOEXCEPT {
- return traits_type::size(any_cast<const Type &>(container));
- }
- [[nodiscard]] static bool resize(any &container, size_type sz) {
- auto * const cont = any_cast<Type>(&container);
- return cont && traits_type::resize(*cont, sz);
- }
- [[nodiscard]] static bool clear(any &container) {
- auto * const cont = any_cast<Type>(&container);
- return cont && traits_type::clear(*cont);
- }
- [[nodiscard]] static iterator begin(any &container) {
- if(auto * const cont = any_cast<Type>(&container); cont) {
- return iterator{traits_type::begin(*cont)};
- }
- return iterator{traits_type::cbegin(any_cast<const Type &>(container))};
- }
- [[nodiscard]] static iterator end(any &container) {
- if(auto * const cont = any_cast<Type>(&container); cont) {
- return iterator{traits_type::end(*cont)};
- }
- return iterator{traits_type::cend(any_cast<const Type &>(container))};
- }
- [[nodiscard]] static std::pair<iterator, bool> insert(any &container, iterator it, meta_any &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>>();
- auto ret = traits_type::insert(*cont, any_cast<const typename Type::iterator &>(it.handle), element ? *element : value.cast<typename Type::value_type>());
- return { iterator{std::move(ret.first)}, ret.second };
- }
- }
- return {};
- }
- [[nodiscard]] static std::pair<iterator, bool> erase(any &container, iterator it) {
- if(auto * const cont = any_cast<Type>(&container); cont) {
- auto ret = traits_type::erase(*cont, any_cast<const typename Type::iterator &>(it.handle));
- return { iterator{std::move(ret.first)}, ret.second };
- }
- return {};
- }
- [[nodiscard]] static meta_any get(any &container, size_type pos) {
- if(auto * const cont = any_cast<Type>(&container); cont) {
- return meta_any{std::in_place_type<typename Type::reference>, traits_type::get(*cont, pos)};
- }
- return meta_any{std::in_place_type<typename Type::const_reference>, traits_type::cget(any_cast<const Type &>(container), pos)};
- }
- };
- /**
- * @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_fn();
- }
- /**
- * @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(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 clear_fn(storage);
- }
- /**
- * @brief Returns an iterator to the first element of a container.
- * @return An iterator to the first element of the container.
- */
- [[nodiscard]] inline meta_sequence_container::iterator meta_sequence_container::begin() {
- return begin_fn(storage);
- }
- /**
- * @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 end_fn(storage);
- }
- /**
- * @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 pair consisting of an iterator to the inserted element (in case of
- * success) and a bool denoting whether the insertion took place.
- */
- inline std::pair<meta_sequence_container::iterator, bool> meta_sequence_container::insert(iterator it, meta_any value) {
- return insert_fn(storage, it, value);
- }
- /**
- * @brief Removes a given element from a container.
- * @param it Iterator to the element to remove.
- * @return A pair consisting of an iterator following the last removed element
- * (in case of success) and a bool denoting whether the insertion took place.
- */
- inline std::pair<meta_sequence_container::iterator, bool> meta_sequence_container::erase(iterator it) {
- return erase_fn(storage, it);
- }
- /**
- * @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[](size_type pos) {
- return get_fn(storage, pos);
- }
- /**
- * @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 Opaque iterator for associative containers. */
- class meta_associative_container::meta_iterator {
- enum operation { INCR, DEREF };
- using vtable_type = void(const operation, const any &, void *);
- template<bool KeyOnly, typename It>
- static void basic_vtable(const operation op, const any &from, void *to) {
- switch(op) {
- case operation::INCR:
- ++any_cast<It &>(const_cast<any &>(from));
- break;
- case operation::DEREF:
- const auto &it = any_cast<const It &>(from);
- if constexpr(KeyOnly) {
- static_cast<std::pair<meta_any, meta_any> *>(to)->first.emplace<decltype(*it)>(*it);
- } else {
- static_cast<std::pair<meta_any, meta_any> *>(to)->first.emplace<decltype((it->first))>(it->first);
- static_cast<std::pair<meta_any, meta_any> *>(to)->second.emplace<decltype((it->second))>(it->second);
- }
- break;
- }
- }
- public:
- /*! @brief Signed integer type. */
- using difference_type = std::ptrdiff_t;
- /*! @brief Type of elements returned by the iterator. */
- using value_type = std::pair<meta_any, meta_any>;
- /*! @brief Pointer type, `void` on purpose. */
- using pointer = void;
- /*! @brief Reference type, it is **not** an actual reference. */
- using reference = value_type;
- /*! @brief Iterator category. */
- using iterator_category = std::input_iterator_tag;
- /*! @brief Default constructor. */
- meta_iterator() ENTT_NOEXCEPT = default;
- /**
- * @brief Constructs an meta iterator from a given iterator.
- * @tparam KeyOnly True if the container is also key-only, false otherwise.
- * @tparam It Type of actual iterator with which to build the meta iterator.
- * @param iter The actual iterator with which to build the meta iterator.
- */
- template<bool KeyOnly, typename It>
- meta_iterator(std::integral_constant<bool, KeyOnly>, It iter)
- : vtable{&basic_vtable<KeyOnly, It>},
- handle{std::move(iter)}
- {}
- /*! @brief Pre-increment operator. @return This iterator. */
- meta_iterator & operator++() ENTT_NOEXCEPT {
- return vtable(operation::INCR, handle, nullptr), *this;
- }
- /*! @brief Post-increment operator. @return This iterator. */
- meta_iterator operator++(int) ENTT_NOEXCEPT {
- meta_iterator orig = *this;
- return ++(*this), orig;
- }
- /**
- * @brief Checks if two iterators refer to the same element.
- * @param other The iterator with which to compare.
- * @return True if the iterators refer to the same element, false otherwise.
- */
- [[nodiscard]] bool operator==(const meta_iterator &other) const ENTT_NOEXCEPT {
- return handle == other.handle;
- }
- /**
- * @brief Checks if two iterators refer to the same element.
- * @param other The iterator with which to compare.
- * @return False if the iterators refer to the same element, true otherwise.
- */
- [[nodiscard]] bool operator!=(const meta_iterator &other) const ENTT_NOEXCEPT {
- return !(*this == other);
- }
- /**
- * @brief Indirection operator.
- * @return The element to which the iterator points.
- */
- [[nodiscard]] reference operator*() const {
- reference other;
- vtable(operation::DEREF, handle, &other);
- return other;
- }
- /**
- * @brief Returns false if an iterator is invalid, true otherwise.
- * @return False if the iterator is invalid, true otherwise.
- */
- [[nodiscard]] explicit operator bool() const ENTT_NOEXCEPT {
- return static_cast<bool>(handle);
- }
- private:
- vtable_type *vtable{};
- any handle{};
- };
- template<typename Type>
- struct meta_associative_container::meta_associative_container_proxy {
- using traits_type = meta_associative_container_traits<Type>;
- [[nodiscard]] static meta_type key_type() ENTT_NOEXCEPT {
- return internal::meta_info<typename Type::key_type>::resolve();
- }
- [[nodiscard]] static meta_type mapped_type() ENTT_NOEXCEPT {
- if constexpr(is_key_only_meta_associative_container_v<Type>) {
- return meta_type{};
- } else {
- return internal::meta_info<typename Type::mapped_type>::resolve();
- }
- }
- [[nodiscard]] static meta_type value_type() ENTT_NOEXCEPT {
- return internal::meta_info<typename Type::value_type>::resolve();
- }
- [[nodiscard]] static size_type size(const any &container) ENTT_NOEXCEPT {
- return traits_type::size(any_cast<const Type &>(container));
- }
- [[nodiscard]] static bool clear(any &container) {
- auto * const cont = any_cast<Type>(&container);
- return cont && traits_type::clear(*cont);
- }
- [[nodiscard]] static iterator begin(any &container) {
- if(auto * const cont = any_cast<Type>(&container); cont) {
- return iterator{is_key_only_meta_associative_container<Type>{}, traits_type::begin(*cont)};
- }
- return iterator{is_key_only_meta_associative_container<Type>{}, traits_type::cbegin(any_cast<const Type &>(container))};
- }
- [[nodiscard]] static iterator end(any &container) {
- if(auto * const cont = any_cast<Type>(&container); cont) {
- return iterator{is_key_only_meta_associative_container<Type>{}, traits_type::end(*cont)};
- }
- return iterator{is_key_only_meta_associative_container<Type>{}, traits_type::cend(any_cast<const Type &>(container))};
- }
- [[nodiscard]] static bool insert(any &container, meta_any &key, meta_any &value) {
- if(auto * const cont = any_cast<Type>(&container); cont && key.allow_cast<const typename Type::key_type &>()) {
- if constexpr(is_key_only_meta_associative_container_v<Type>) {
- return traits_type::insert(*cont, key.cast<const typename Type::key_type &>());
- } else {
- return value.allow_cast<const typename Type::mapped_type &>()
- && traits_type::insert(*cont, key.cast<const typename Type::key_type &>(), value.cast<const typename Type::mapped_type &>());
- }
- }
- return false;
- }
- [[nodiscard]] static bool erase(any &container, meta_any &key) {
- if(auto * const cont = any_cast<Type>(&container); cont && key.allow_cast<const typename Type::key_type &>()) {
- return traits_type::erase(*cont, key.cast<const typename Type::key_type &>());
- }
- return false;
- }
- [[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{is_key_only_meta_associative_container<Type>{}, traits_type::find(*cont, key.cast<const typename Type::key_type &>())};
- }
- return iterator{is_key_only_meta_associative_container<Type>{}, traits_type::cfind(any_cast<const Type &>(container), key.cast<const typename Type::key_type &>())};
- }
- return {};
- }
- };
- /**
- * @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_fn();
- }
- /**
- * @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_fn();
- }
- /*! @copydoc meta_sequence_container::value_type */
- [[nodiscard]] inline meta_type meta_associative_container::value_type() const ENTT_NOEXCEPT {
- return value_type_fn();
- }
- /*! @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 begin_fn(storage);
- }
- /*! @copydoc meta_sequence_container::end */
- [[nodiscard]] inline meta_associative_container::iterator meta_associative_container::end() {
- return end_fn(storage);
- }
- /**
- * @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);
- }
- }
- #endif
- // #include "node.hpp"
- // #include "policy.hpp"
- #ifndef ENTT_META_POLICY_HPP
- #define ENTT_META_POLICY_HPP
- namespace entt {
- /*! @brief Empty class type used to request the _as ref_ policy. */
- struct as_ref_t {};
- /*! @brief Empty class type used to request the _as cref_ policy. */
- struct as_cref_t {};
- /*! @brief Empty class type used to request the _as-is_ policy. */
- struct as_is_t {};
- /*! @brief Empty class type used to request the _as void_ policy. */
- struct as_void_t {};
- }
- #endif
- // #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_same_v<Type, Class>, 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_same_v<Type, Class>;
- };
- /**
- * @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_same_v<Type, Class>, 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_same_v<Type, Class>;
- };
- /**
- * @brief Meta function descriptor.
- * @tparam Type Reflected type to which the meta function is associated.
- * @tparam Ret Function return type.
- * @tparam Args Function arguments.
- */
- template<typename Type, typename Ret, typename... Args>
- struct meta_function_descriptor<Type, Ret(*)(Args...)> {
- /*! @brief Meta function return type. */
- using return_type = Ret;
- /*! @brief Meta function arguments. */
- using args_type = type_list<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 = 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... Args>
- static constexpr meta_function_descriptor<Type, Ret(*)(Args...)> get_rid_of_noexcept(Ret(*)(Args...));
- 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 Returns the meta type of the i-th element of a list of arguments.
- * @tparam Args Actual types of arguments.
- * @return The meta type of the i-th element of the list of arguments.
- */
- template<typename... Args>
- [[nodiscard]] static meta_type meta_arg(type_list<Args...>, const std::size_t index) ENTT_NOEXCEPT {
- return internal::meta_arg_node(type_list<Args...>{}, index);
- }
- /**
- * @brief Constructs an instance given a list of erased parameters, if possible.
- * @tparam Type Actual type of the instance to construct.
- * @tparam Args Types of arguments expected.
- * @tparam Index Indexes to use to extract erased arguments from their list.
- * @param args Parameters to use to construct the instance.
- * @return A meta any containing the new instance, if 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 Type{(args+Index)->cast<Args>()...};
- }
- return {};
- }
- /**
- * @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_function_v<std::remove_reference_t<std::remove_pointer_t<decltype(Data)>>>) {
- using data_type = type_list_element_t<1u, typename meta_function_helper_t<Type, decltype(Data)>::args_type>;
- if(auto * const clazz = instance->try_cast<Type>(); clazz && value.allow_cast<data_type>()) {
- Data(*clazz, value.cast<data_type>());
- return true;
- }
- } else if constexpr(std::is_member_function_pointer_v<decltype(Data)>) {
- using data_type = type_list_element_t<0u, typename meta_function_helper_t<Type, decltype(Data)>::args_type>;
- if(auto * const clazz = instance->try_cast<Type>(); clazz && value.allow_cast<data_type>()) {
- (clazz->*Data)(value.cast<data_type>());
- return true;
- }
- } else if constexpr(std::is_member_object_pointer_v<decltype(Data)>) {
- using data_type = std::remove_reference_t<decltype(std::declval<Type>().*Data)>;
- 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>()) {
- clazz->*Data = 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 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.
- */
- template<typename Policy = as_is_t, typename Type>
- meta_any meta_dispatch(Type &&value) {
- if constexpr(std::is_same_v<Policy, as_void_t>) {
- return meta_any{std::in_place_type<void>, std::forward<Type>(value)};
- } 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 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_function_v<std::remove_reference_t<std::remove_pointer_t<decltype(Data)>>>) {
- auto * const clazz = instance->try_cast<std::conditional_t<std::is_invocable_v<decltype(Data), const Type &>, const Type, Type>>();
- return clazz ? meta_dispatch<Policy>(Data(*clazz)) : meta_any{};
- } else if constexpr(std::is_member_function_pointer_v<decltype(Data)>) {
- auto * const clazz = instance->try_cast<std::conditional_t<std::is_invocable_v<decltype(Data), const Type &>, const Type, Type>>();
- return clazz ? meta_dispatch<Policy>((clazz->*Data)()) : meta_any{};
- } else if constexpr(std::is_member_object_pointer_v<decltype(Data)>) {
- if constexpr(!std::is_array_v<std::remove_cv_t<std::remove_reference_t<decltype(std::declval<Type>().*Data)>>>) {
- if(auto * clazz = instance->try_cast<Type>(); clazz) {
- return meta_dispatch<Policy>(clazz->*Data);
- } else if(auto * fallback = instance->try_cast<const Type>(); fallback) {
- return meta_dispatch<Policy>(fallback->*Data);
- }
- }
- 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);
- }
- }
- /**
- * @brief Invokes a function given a list of erased parameters, if possible.
- * @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).
- * @tparam Index Indexes to use to extract erased arguments from their list.
- * @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, std::size_t... Index>
- [[nodiscard]] std::enable_if_t<!std::is_invocable_v<decltype(Candidate)>, meta_any> meta_invoke([[maybe_unused]] meta_handle instance, meta_any *args, std::index_sequence<Index...>) {
- using descriptor = meta_function_helper_t<Type, decltype(Candidate)>;
- const auto invoke = [](auto &&maybe_clazz, auto &&... other) {
- if constexpr(std::is_member_function_pointer_v<decltype(Candidate)>) {
- if constexpr(std::is_void_v<typename descriptor::return_type>) {
- (std::forward<decltype(maybe_clazz)>(maybe_clazz).*Candidate)(std::forward<decltype(other)>(other)...);
- return meta_any{std::in_place_type<void>};
- } else {
- return meta_dispatch<Policy>((std::forward<decltype(maybe_clazz)>(maybe_clazz).*Candidate)(std::forward<decltype(other)>(other)...));
- }
- } else {
- if constexpr(std::is_void_v<typename descriptor::return_type>) {
- Candidate(std::forward<decltype(maybe_clazz)>(maybe_clazz), std::forward<decltype(other)>(other)...);
- return meta_any{std::in_place_type<void>};
- } else {
- return meta_dispatch<Policy>(Candidate(std::forward<decltype(maybe_clazz)>(maybe_clazz), std::forward<decltype(other)>(other)...));
- }
- }
- };
- if constexpr(std::is_invocable_v<decltype(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 invoke(*clazz, (args+Index)->cast<type_list_element_t<Index, typename descriptor::args_type>>()...);
- }
- } else if constexpr(std::is_invocable_v<decltype(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 invoke(*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 invoke((args+Index)->cast<type_list_element_t<Index, typename descriptor::args_type>>()...);
- }
- }
- return meta_any{};
- }
- /**
- * @brief Invokes a function given a list of erased parameters, if possible.
- * @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).
- * @tparam Index Indexes to use to extract erased arguments from their list.
- * @return A meta any containing the returned value, if any.
- */
- template<typename Type, auto Candidate, typename Policy = as_is_t, std::size_t... Index>
- [[nodiscard]] std::enable_if_t<std::is_invocable_v<decltype(Candidate)>, meta_any> meta_invoke(meta_handle, meta_any *, std::index_sequence<Index...>) {
- if constexpr(std::is_void_v<decltype(Candidate())>) {
- Candidate();
- return meta_any{std::in_place_type<void>};
- } else {
- return meta_dispatch<Policy>(Candidate());
- }
- }
- }
- #endif
- namespace entt {
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- namespace internal {
- template<typename Node>
- [[nodiscard]] bool find_if(const Node *candidate, const Node *node) ENTT_NOEXCEPT {
- return node && (node == candidate || find_if(candidate, node->next));
- }
- template<typename Id, typename Node>
- [[nodiscard]] bool find_if_not(const Id id, Node *node, const Node *owner) ENTT_NOEXCEPT {
- if constexpr(std::is_pointer_v<Id>) {
- return node && ((*node->id == *id && node != owner) || find_if_not(id, node->next, owner));
- } else {
- return node && ((node->id == id && node != owner) || find_if_not(id, node->next, owner));
- }
- }
- }
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /**
- * @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...>
- struct 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>
- struct meta_factory<Type, Spec...>: public meta_factory<Type> {
- private:
- template<std::size_t Step = 0, std::size_t... Index, typename... Property, typename... Other>
- void unpack(std::index_sequence<Index...>, std::tuple<Property...> property, Other &&... other) {
- unroll<Step>(choice<3>, std::move(std::get<Index>(property))..., std::forward<Other>(other)...);
- }
- template<std::size_t Step = 0, typename... Property, typename... Other>
- void unroll(choice_t<3>, std::tuple<Property...> property, Other &&... other) {
- unpack<Step>(std::index_sequence_for<Property...>{}, std::move(property), std::forward<Other>(other)...);
- }
- template<std::size_t Step = 0, typename... Property, typename... Other>
- void unroll(choice_t<2>, std::pair<Property...> property, Other &&... other) {
- assign<Step>(std::move(property.first), std::move(property.second));
- unroll<Step+1>(choice<3>, std::forward<Other>(other)...);
- }
- template<std::size_t Step = 0, typename Property, typename... Other>
- std::enable_if_t<!std::is_invocable_v<Property>>
- unroll(choice_t<1>, Property &&property, Other &&... other) {
- assign<Step>(std::forward<Property>(property));
- unroll<Step+1>(choice<3>, std::forward<Other>(other)...);
- }
- template<std::size_t Step = 0, typename Func, typename... Other>
- void unroll(choice_t<0>, Func &&invocable, Other &&... other) {
- unroll<Step>(choice<3>, std::forward<Func>(invocable)(), std::forward<Other>(other)...);
- }
- template<std::size_t>
- void unroll(choice_t<0>) {}
- template<std::size_t = 0, typename Key>
- void assign(Key &&key, meta_any value = {}) {
- static meta_any property[2u]{};
- static internal::meta_prop_node node{
- nullptr,
- property[0u],
- property[1u]
- };
- entt::meta_any instance{std::forward<Key>(key)};
- ENTT_ASSERT(!internal::find_if_not(&instance, *curr, &node), "Duplicate key");
- property[0u] = std::move(instance);
- property[1u] = std::move(value);
- if(!internal::find_if(&node, *curr)) {
- node.next = *curr;
- *curr = &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
- : curr{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>
- auto prop(PropertyOrKey &&property_or_key, Value &&... value) && {
- if constexpr(sizeof...(Value) == 0) {
- unroll(choice<3>, std::forward<PropertyOrKey>(property_or_key));
- } else {
- assign(std::forward<PropertyOrKey>(property_or_key), std::forward<Value>(value)...);
- }
- return meta_factory<Type, Spec..., PropertyOrKey, Value...>{curr};
- }
- /**
- * @brief Assigns properties to the last meta object created.
- *
- * Both the keys and the values (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>
- auto props(Property... property) && {
- unroll(choice<3>, std::forward<Property>(property)...);
- return meta_factory<Type, Spec..., Property...>{curr};
- }
- private:
- internal::meta_prop_node **curr;
- };
- /**
- * @brief Basic meta factory to be used for reflection purposes.
- * @tparam Type Reflected type for which the factory was created.
- */
- template<typename Type>
- struct meta_factory<Type> {
- /**
- * @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()) {
- auto * const node = internal::meta_info<Type>::resolve();
- ENTT_ASSERT(!internal::find_if_not(id, *internal::meta_context::global(), node), "Duplicate identifier");
- node->id = id;
- if(!internal::find_if(node, *internal::meta_context::global())) {
- node->next = *internal::meta_context::global();
- *internal::meta_context::global() = node;
- }
- return meta_factory<Type, Type>{&node->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_base_of_v<Base, Type>, "Invalid base type");
- auto * const type = internal::meta_info<Type>::resolve();
- static internal::meta_base_node node{
- type,
- nullptr,
- &internal::meta_info<Base>::resolve,
- [](const void *instance) ENTT_NOEXCEPT -> const void * {
- return static_cast<const Base *>(static_cast<const Type *>(instance));
- }
- };
- if(!internal::find_if(&node, type->base)) {
- node.next = type->base;
- type->base = &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>
- std::enable_if_t<std::is_member_function_pointer_v<decltype(Candidate)>, meta_factory<Type>> conv() ENTT_NOEXCEPT {
- using conv_type = std::invoke_result_t<decltype(Candidate), Type &>;
- auto * const type = internal::meta_info<Type>::resolve();
- static internal::meta_conv_node node{
- type,
- nullptr,
- &internal::meta_info<conv_type>::resolve,
- [](const void *instance) -> meta_any {
- return (static_cast<const Type *>(instance)->*Candidate)();
- }
- };
- if(!internal::find_if(&node, type->conv)) {
- node.next = type->conv;
- type->conv = &node;
- }
- return meta_factory<Type>{};
- }
- /*! @copydoc conv */
- template<auto Candidate>
- std::enable_if_t<!std::is_member_function_pointer_v<decltype(Candidate)>, meta_factory<Type>> conv() ENTT_NOEXCEPT {
- using conv_type = std::invoke_result_t<decltype(Candidate), Type &>;
- auto * const type = internal::meta_info<Type>::resolve();
- static internal::meta_conv_node node{
- type,
- nullptr,
- &internal::meta_info<conv_type>::resolve,
- [](const void *instance) -> meta_any {
- return Candidate(*static_cast<const Type *>(instance));
- }
- };
- if(!internal::find_if(&node, type->conv)) {
- node.next = type->conv;
- type->conv = &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_assert(std::is_convertible_v<Type, To>, "Could not convert to the required type");
- auto * const type = internal::meta_info<Type>::resolve();
- static internal::meta_conv_node node{
- type,
- nullptr,
- &internal::meta_info<To>::resolve,
- [](const void *instance) -> meta_any {
- return static_cast<To>(*static_cast<const Type *>(instance));
- }
- };
- if(!internal::find_if(&node, type->conv)) {
- node.next = type->conv;
- type->conv = &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(std::is_same_v<std::decay_t<typename descriptor::return_type>, Type>, "The function doesn't return an object of the required type");
- auto * const type = internal::meta_info<Type>::resolve();
- static internal::meta_ctor_node node{
- type,
- nullptr,
- nullptr,
- descriptor::args_type::size,
- [](const typename internal::meta_ctor_node::size_type index) ENTT_NOEXCEPT {
- return meta_arg(typename descriptor::args_type{}, index);
- },
- [](meta_any * const args) {
- return meta_invoke<Type, Candidate, Policy>({}, args, std::make_index_sequence<descriptor::args_type::size>{});
- }
- };
- if(!internal::find_if(&node, type->ctor)) {
- node.next = type->ctor;
- type->ctor = &node;
- }
- return meta_factory<Type, std::integral_constant<decltype(Candidate), Candidate>>{&node.prop};
- }
- /**
- * @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...)>;
- auto * const type = internal::meta_info<Type>::resolve();
- static internal::meta_ctor_node node{
- type,
- nullptr,
- nullptr,
- descriptor::args_type::size,
- [](const typename internal::meta_ctor_node::size_type index) ENTT_NOEXCEPT {
- return meta_arg(typename descriptor::args_type{}, index);
- },
- [](meta_any * const args) {
- return meta_construct<Type, Args...>(args, std::make_index_sequence<descriptor::args_type::size>{});
- }
- };
- if(!internal::find_if(&node, type->ctor)) {
- node.next = type->ctor;
- type->ctor = &node;
- }
- return meta_factory<Type, Type(Args...)>{&node.prop};
- }
- /**
- * @brief Assigns a meta destructor to a meta type.
- *
- * Free functions can be assigned to meta types in the role of destructors.
- * The signature of the function should identical to the following:
- *
- * @code{.cpp}
- * void(Type &);
- * @endcode
- *
- * 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");
- auto * const type = internal::meta_info<Type>::resolve();
- type->dtor = [](void *instance) {
- 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)>) {
- return data<Data, Data, Policy>(id);
- } else {
- using data_type = std::remove_pointer_t<decltype(Data)>;
- auto * const type = internal::meta_info<Type>::resolve();
- static internal::meta_data_node node{
- {},
- type,
- nullptr,
- nullptr,
- std::is_same_v<Type, data_type> || std::is_const_v<data_type>,
- true,
- &internal::meta_info<data_type>::resolve,
- &meta_setter<Type, Data>,
- &meta_getter<Type, Data, Policy>
- };
- ENTT_ASSERT(!internal::find_if_not(id, type->data, &node), "Duplicate identifier");
- node.id = id;
- if(!internal::find_if(&node, type->data)) {
- node.next = type->data;
- type->data = &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 underlying_type = std::remove_reference_t<std::invoke_result_t<decltype(Getter), Type &>>;
- auto * const type = internal::meta_info<Type>::resolve();
- static internal::meta_data_node node{
- {},
- type,
- nullptr,
- nullptr,
- std::is_same_v<decltype(Setter), std::nullptr_t> || (std::is_member_object_pointer_v<decltype(Setter)> && std::is_const_v<underlying_type>),
- false,
- &internal::meta_info<underlying_type>::resolve,
- &meta_setter<Type, Setter>,
- &meta_getter<Type, Getter, Policy>
- };
- ENTT_ASSERT(!internal::find_if_not(id, type->data, &node), "Duplicate identifier");
- node.id = id;
- if(!internal::find_if(&node, type->data)) {
- node.next = type->data;
- type->data = &node;
- }
- return meta_factory<Type, std::integral_constant<decltype(Setter), Setter>, std::integral_constant<decltype(Getter), Getter>>{&node.prop};
- }
- /**
- * @brief Assigns a meta funcion 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)>;
- auto * const type = internal::meta_info<Type>::resolve();
- static internal::meta_func_node node{
- {},
- type,
- nullptr,
- nullptr,
- descriptor::args_type::size,
- descriptor::is_const,
- descriptor::is_static,
- &internal::meta_info<std::conditional_t<std::is_same_v<Policy, as_void_t>, void, typename descriptor::return_type>>::resolve,
- [](const typename internal::meta_func_node::size_type index) ENTT_NOEXCEPT {
- return meta_arg(typename descriptor::args_type{}, index);
- },
- [](meta_handle instance, meta_any *args) {
- return meta_invoke<Type, Candidate, Policy>(std::move(instance), args, std::make_index_sequence<descriptor::args_type::size>{});
- }
- };
- for(auto *it = &type->func; *it; it = &(*it)->next) {
- if(*it == &node) {
- *it = node.next;
- break;
- }
- }
- internal::meta_func_node **it = &type->func;
- for(; *it && (*it)->id != id; it = &(*it)->next);
- for(; *it && (*it)->id == id && (*it)->arity < node.arity; it = &(*it)->next);
- node.id = id;
- node.next = *it;
- *it = &node;
- return meta_factory<Type, std::integral_constant<decltype(Candidate), Candidate>>{&node.prop};
- }
- };
- /**
- * @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_info<Type>::resolve();
- // extended meta factory to allow assigning properties to opaque meta types
- return meta_factory<Type, Type>{&node->prop};
- }
- }
- #endif
- // #include "meta/meta.hpp"
- #ifndef ENTT_META_META_HPP
- #define ENTT_META_META_HPP
- #include <cstddef>
- #include <functional>
- #include <iterator>
- #include <memory>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- // #include "../core/any.hpp"
- // #include "../core/fwd.hpp"
- // #include "../core/utility.hpp"
- // #include "../core/type_info.hpp"
- // #include "../core/type_traits.hpp"
- // #include "adl_pointer.hpp"
- // #include "ctx.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 {
- template<typename>
- struct meta_sequence_container_proxy;
- 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_fn{&meta_sequence_container_proxy<Type>::value_type},
- size_fn{&meta_sequence_container_proxy<Type>::size},
- resize_fn{&meta_sequence_container_proxy<Type>::resize},
- clear_fn{&meta_sequence_container_proxy<Type>::clear},
- begin_fn{&meta_sequence_container_proxy<Type>::begin},
- end_fn{&meta_sequence_container_proxy<Type>::end},
- insert_fn{&meta_sequence_container_proxy<Type>::insert},
- erase_fn{&meta_sequence_container_proxy<Type>::erase},
- get_fn{&meta_sequence_container_proxy<Type>::get},
- storage{std::move(instance)}
- {}
- [[nodiscard]] inline meta_type value_type() const ENTT_NOEXCEPT;
- [[nodiscard]] inline size_type size() const ENTT_NOEXCEPT;
- inline bool resize(size_type);
- inline bool clear();
- [[nodiscard]] inline iterator begin();
- [[nodiscard]] inline iterator end();
- inline std::pair<iterator, bool> insert(iterator, meta_any);
- inline std::pair<iterator, bool> erase(iterator);
- [[nodiscard]] inline meta_any operator[](size_type);
- [[nodiscard]] inline explicit operator bool() const ENTT_NOEXCEPT;
- private:
- meta_type(* value_type_fn)() ENTT_NOEXCEPT = nullptr;
- size_type(* size_fn)(const any &) ENTT_NOEXCEPT = nullptr;
- bool(* resize_fn)(any &, size_type) = nullptr;
- bool(* clear_fn)(any &) = nullptr;
- iterator(* begin_fn)(any &) = nullptr;
- iterator(* end_fn)(any &) = nullptr;
- std::pair<iterator, bool>(* insert_fn)(any &, iterator, meta_any &) = nullptr;
- std::pair<iterator, bool>(* erase_fn)(any &, iterator) = nullptr;
- meta_any(* get_fn)(any &, size_type) = nullptr;
- any storage{};
- };
- /*! @brief Proxy object for associative containers. */
- class meta_associative_container {
- template<typename>
- struct meta_associative_container_proxy;
- 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{is_key_only_meta_associative_container_v<Type>},
- key_type_fn{&meta_associative_container_proxy<Type>::key_type},
- mapped_type_fn{&meta_associative_container_proxy<Type>::mapped_type},
- value_type_fn{&meta_associative_container_proxy<Type>::value_type},
- size_fn{&meta_associative_container_proxy<Type>::size},
- clear_fn{&meta_associative_container_proxy<Type>::clear},
- begin_fn{&meta_associative_container_proxy<Type>::begin},
- end_fn{&meta_associative_container_proxy<Type>::end},
- insert_fn{&meta_associative_container_proxy<Type>::insert},
- erase_fn{&meta_associative_container_proxy<Type>::erase},
- find_fn{&meta_associative_container_proxy<Type>::find},
- storage{std::move(instance)}
- {}
- [[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{};
- meta_type(* key_type_fn)() ENTT_NOEXCEPT = nullptr;
- meta_type(* mapped_type_fn)() ENTT_NOEXCEPT = nullptr;
- meta_type(* value_type_fn)() ENTT_NOEXCEPT = nullptr;
- size_type(* size_fn)(const any &) ENTT_NOEXCEPT = nullptr;
- bool(* clear_fn)(any &) = nullptr;
- iterator(* begin_fn)(any &) = nullptr;
- iterator(* end_fn)(any &) = 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 { DTOR, 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 &from, [[maybe_unused]] void *to) {
- static_assert(std::is_same_v<std::remove_reference_t<std::remove_const_t<Type>>, Type>, "Invalid type");
- if constexpr(!std::is_void_v<Type>) {
- switch(op) {
- case operation::DTOR:
- if(auto *curr = static_cast<internal::meta_type_node *>(to); curr->dtor && from.owner()) {
- curr->dtor(const_cast<any &>(from).data());
- }
- break;
- case operation::DEREF:
- if constexpr(is_meta_pointer_like_v<Type>) {
- using element_type = std::remove_const_t<typename std::pointer_traits<Type>::element_type>;
- if constexpr(std::is_function_v<element_type>) {
- *static_cast<meta_any *>(to) = any_cast<Type>(from);
- } 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 &>(from)));
- static_cast<meta_any *>(to)->emplace<in_place_type>(adl_meta_pointer_like<Type>::dereference(any_cast<const Type &>(from)));
- }
- }
- case operation::SEQ:
- if constexpr(is_complete_v<meta_sequence_container_traits<Type>>) {
- *static_cast<meta_sequence_container *>(to) = { std::in_place_type<Type>, std::move(const_cast<any &>(from)) };
- }
- break;
- case operation::ASSOC:
- if constexpr(is_complete_v<meta_associative_container_traits<Type>>) {
- *static_cast<meta_associative_container *>(to) = { std::in_place_type<Type>, std::move(const_cast<any &>(from)) };
- }
- break;
- }
- }
- }
- 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_info<Type>::resolve()},
- vtable{&basic_vtable<std::remove_const_t<std::remove_reference_t<Type>>>}
- {}
- /**
- * @brief Constructs a wrapper that holds an unmanaged object.
- * @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>
- meta_any(std::reference_wrapper<Type> value)
- : meta_any{}
- {
- // invokes deprecated assignment operator (and avoids issues with vs2017)
- *this = value;
- }
- /**
- * @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)
- : storage{std::forward<Type>(value)},
- node{internal::meta_info<std::decay_t<Type>>::resolve()},
- vtable{&basic_vtable<std::decay_t<Type>>}
- {}
- /**
- * @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() {
- vtable(operation::DTOR, storage, node);
- }
- /**
- * @brief Copy assignment operator.
- * @param other The instance to copy from.
- * @return This meta any object.
- */
- meta_any & operator=(const meta_any &other) {
- std::exchange(vtable, other.vtable)(operation::DTOR, storage, node);
- 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 {
- std::exchange(vtable, std::exchange(other.vtable, &basic_vtable<void>))(operation::DTOR, storage, node);
- 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>
- [[deprecated("Use std::in_place_type<T &>, entt::make_meta<T &>, emplace<Type &> or forward_as_meta instead")]]
- meta_any & operator=(std::reference_wrapper<Type> value) {
- emplace<Type &>(value.get());
- 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;
- }
- /**
- * @brief Returns the type of the underlying object.
- * @return The type of the underlying object, if any.
- */
- [[nodiscard]] inline meta_type type() const ENTT_NOEXCEPT;
- /**
- * @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 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 must be 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(node) {
- if(const auto info = type_id<Type>(); node->info == info) {
- return any_cast<Type>(&storage);
- } else if(const auto *base = internal::meta_visit<&internal::meta_type_node::base>([info](const auto *curr) { return curr->type()->info == info; }, node); base) {
- return static_cast<const Type *>(base->cast(storage.data()));
- }
- }
- return nullptr;
- }
- /*! @copydoc try_cast */
- template<typename Type>
- [[nodiscard]] Type * try_cast() {
- if(node) {
- if(const auto info = type_id<Type>(); node->info == info) {
- return any_cast<Type>(&storage);
- } else if(const auto *base = internal::meta_visit<&internal::meta_type_node::base>([info](const auto *curr) { return curr->type()->info == info; }, node); base) {
- return static_cast<Type *>(const_cast<constness_as_t<void, Type> *>(base->cast(static_cast<constness_as_t<any, Type> &>(storage).data())));
- }
- }
- 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 in 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.
- * @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 {
- if(try_cast<std::remove_reference_t<Type>>() != nullptr) {
- return as_ref();
- } else if(node) {
- if(const auto * const conv = internal::meta_visit<&internal::meta_type_node::conv>([info = type_id<Type>()](const auto *curr) { return curr->type()->info == info; }, node); conv) {
- return conv->conv(storage.data());
- }
- }
- return {};
- }
- /**
- * @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() {
- // forces const on non-reference types to make them work also with wrappers for const references
- if(try_cast<std::remove_reference_t<const Type>>() != nullptr) {
- return true;
- } else if(node) {
- if(const auto * const conv = internal::meta_visit<&internal::meta_type_node::conv>([info = type_id<Type>()](const auto *curr) { return curr->type()->info == info; }, node); conv) {
- *this = conv->conv(std::as_const(storage).data());
- return true;
- }
- }
- return false;
- }
- /**
- * @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) {
- std::exchange(vtable, &basic_vtable<std::remove_const_t<std::remove_reference_t<Type>>>)(operation::DTOR, storage, node);
- storage.emplace<Type>(std::forward<Args>(args)...);
- node = internal::meta_info<Type>::resolve();
- }
- /*! @brief Destroys contained object */
- void reset() {
- std::exchange(vtable, &basic_vtable<void>)(operation::DTOR, storage, node);
- 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 {
- meta_sequence_container proxy;
- vtable(operation::SEQ, storage.as_ref(), &proxy);
- return proxy;
- }
- /*! @copydoc as_sequence_container */
- [[nodiscard]] meta_sequence_container as_sequence_container() const ENTT_NOEXCEPT {
- meta_sequence_container proxy;
- vtable(operation::SEQ, storage.as_ref(), &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 {
- meta_associative_container proxy;
- vtable(operation::ASSOC, storage.as_ref(), &proxy);
- return proxy;
- }
- /*! @copydoc as_associative_container */
- [[nodiscard]] meta_associative_container as_associative_container() const ENTT_NOEXCEPT {
- meta_associative_container proxy;
- vtable(operation::ASSOC, storage.as_ref(), &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);
- }
- /**
- * @brief Checks if two wrappers differ in their content.
- * @param other Wrapper with which to compare.
- * @return False if the two objects differ in their content, true otherwise.
- */
- [[nodiscard]] bool operator==(const meta_any &other) const {
- return (!node && !other.node) || (node && other.node && node->info == other.node->info && storage == other.storage);
- }
- /**
- * @brief Aliasing constructor.
- * @return A wrapper that shares a reference to an unmanaged object.
- */
- [[nodiscard]] meta_any as_ref() ENTT_NOEXCEPT {
- return meta_any{*this, storage.as_ref()};
- }
- /*! @copydoc as_ref */
- [[nodiscard]] meta_any as_ref() const ENTT_NOEXCEPT {
- return meta_any{*this, storage.as_ref()};
- }
- 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 constructors. */
- struct meta_ctor {
- /*! @brief Node type. */
- using node_type = internal::meta_ctor_node;
- /*! @brief Unsigned integer type. */
- using size_type = typename node_type::size_type;
- /*! @copydoc meta_prop::meta_prop */
- meta_ctor(const node_type *curr = nullptr) ENTT_NOEXCEPT
- : node{curr}
- {}
- /**
- * @brief Returns the type to which an object belongs.
- * @return The type to which the object belongs.
- */
- [[nodiscard]] inline meta_type parent() const ENTT_NOEXCEPT;
- /**
- * @brief Returns the number of arguments accepted by a constructor.
- * @return The number of arguments accepted by the constructor.
- */
- [[nodiscard]] size_type arity() const ENTT_NOEXCEPT {
- return node->arity;
- }
- /**
- * @brief Returns the type of the i-th argument of a constructor.
- * @param index Index of the argument of which to return the type.
- * @return The type of the i-th argument of a constructor.
- */
- [[nodiscard]] meta_type arg(size_type index) const ENTT_NOEXCEPT;
- /**
- * @brief Creates an instance of the underlying type, if possible.
- *
- * Parameters must be such that a cast or conversion to the required types
- * is possible. Otherwise, an empty and thus invalid wrapper is returned.
- *
- * @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 invoke(meta_any * const args, const size_type sz) const {
- return sz == arity() ? node->invoke(args) : meta_any{};
- }
- /**
- * @copybrief invoke
- *
- * @sa invoke
- *
- * @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 invoke([[maybe_unused]] Args &&... args) const {
- meta_any arguments[sizeof...(Args) + 1u]{std::forward<Args>(args)...};
- return invoke(arguments, sizeof...(Args));
- }
- /**
- * @brief Returns a range to use to visit all properties.
- * @return An iterable range to use to visit all properties.
- */
- [[nodiscard]] meta_range<meta_prop> prop() const ENTT_NOEXCEPT {
- return node->prop;
- }
- /**
- * @brief Returns the property associated with a given key.
- * @param key The key to use to search for a property.
- * @return The property associated with the given key, if any.
- */
- [[nodiscard]] meta_prop prop(meta_any key) const {
- return internal::meta_visit<&node_type::prop>([&key](const auto *curr) { return curr->id == 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);
- }
- private:
- const node_type *node;
- };
- /*! @brief Opaque wrapper for data members. */
- struct meta_data {
- /*! @brief Node type. */
- using node_type = internal::meta_data_node;
- /*! @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;
- }
- /*! @copydoc meta_ctor::parent */
- [[nodiscard]] inline meta_type parent() const ENTT_NOEXCEPT;
- /**
- * @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->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->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. Otherwise, invoking the setter results in an undefined
- * behavior.<br/>
- * The type of the value must be 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. Otherwise, invoking the getter results in an undefined behavior.
- *
- * @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));
- }
- /*! @copydoc meta_ctor::prop */
- [[nodiscard]] meta_range<meta_prop> prop() const ENTT_NOEXCEPT {
- return node->prop;
- }
- /**
- * @brief Returns the property associated with a given key.
- * @param key The key to use to search for a property.
- * @return The property associated with the given key, if any.
- */
- [[nodiscard]] meta_prop prop(meta_any key) const {
- return internal::meta_visit<&node_type::prop>([&key](const auto *curr) { return curr->id == 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);
- }
- 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;
- }
- /*! @copydoc meta_ctor::parent */
- [[nodiscard]] inline meta_type parent() const ENTT_NOEXCEPT;
- /**
- * @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->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->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(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. Otherwise, invoking the underlying function results in an
- * undefined behavior.
- *
- * @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_ctor::prop */
- [[nodiscard]] meta_range<meta_prop> prop() const ENTT_NOEXCEPT {
- return node->prop;
- }
- /**
- * @brief Returns the property associated with a given key.
- * @param key The key to use to search for a property.
- * @return The property associated with the given key, if any.
- */
- [[nodiscard]] meta_prop prop(meta_any key) const {
- return internal::meta_visit<&node_type::prop>([&key](const auto *curr) { return curr->id == 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);
- }
- private:
- const node_type *node;
- };
- /*! @brief Opaque wrapper for types. */
- class meta_type {
- static bool can_cast_or_convert(const internal::meta_type_node *type, const type_info info) ENTT_NOEXCEPT {
- if(type->info == info) {
- return true;
- }
- for(const auto *curr = type->conv; curr; curr = curr->next) {
- if(curr->type()->info == info) {
- return true;
- }
- }
- for(const auto *curr = type->base; curr; curr = curr->next) {
- if(auto *target = curr->type(); can_cast_or_convert(target, info)) {
- return true;
- }
- }
- return false;
- }
- template<typename... Args, auto... Index>
- [[nodiscard]] static const internal::meta_ctor_node * ctor(const internal::meta_ctor_node *curr, std::index_sequence<Index...>) {
- for(; curr; curr = curr->next) {
- if(curr->arity == sizeof...(Args) && (can_cast_or_convert(internal::meta_info<Args>::resolve(), curr->arg(Index).info()) && ...)) {
- return curr;
- }
- }
- return nullptr;
- }
- template<auto... Member, typename Node>
- void unregister_all(Node **curr) {
- while(*curr) {
- (unregister_all(&((*curr)->*Member)), ...);
- *curr = std::exchange((*curr)->next, nullptr);
- }
- }
- 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(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(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]] 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 void or not.
- * @return True if the underlying type is void, false otherwise.
- */
- [[nodiscard]] bool is_void() const ENTT_NOEXCEPT {
- return node->is_void;
- }
- /**
- * @brief Checks whether a type refers to an integral type or not.
- * @return True if the underlying type is an integral type, false otherwise.
- */
- [[nodiscard]] bool is_integral() const ENTT_NOEXCEPT {
- return node->is_integral;
- }
- /**
- * @brief Checks whether a type refers to a floating-point type or not.
- * @return True if the underlying type is a floating-point type, false
- * otherwise.
- */
- [[nodiscard]] bool is_floating_point() const ENTT_NOEXCEPT {
- return node->is_floating_point;
- }
- /**
- * @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->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->is_enum;
- }
- /**
- * @brief Checks whether a type refers to an union or not.
- * @return True if the underlying type is an union, false otherwise.
- */
- [[nodiscard]] bool is_union() const ENTT_NOEXCEPT {
- return node->is_union;
- }
- /**
- * @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->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->is_pointer;
- }
- /**
- * @brief Checks whether a type refers to a function pointer or not.
- * @return True if the underlying type is a function pointer, false
- * otherwise.
- */
- [[nodiscard]] bool is_function_pointer() const ENTT_NOEXCEPT {
- return node->is_function_pointer;
- }
- /**
- * @brief Checks whether a type refers to a pointer to data member or not.
- * @return True if the underlying type is a pointer to data member, false
- * otherwise.
- */
- [[nodiscard]] bool is_member_object_pointer() const ENTT_NOEXCEPT {
- return node->is_member_object_pointer;
- }
- /**
- * @brief Checks whether a type refers to a pointer to member function or
- * not.
- * @return True if the underlying type is a pointer to member function,
- * false otherwise.
- */
- [[nodiscard]] bool is_member_function_pointer() const ENTT_NOEXCEPT {
- return node->is_member_function_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->is_pointer_like;
- }
- /**
- * @brief Checks whether a type refers to a sequence container or not.
- * @return True if the type is a sequence container, false otherwise.
- */
- [[nodiscard]] bool is_sequence_container() const ENTT_NOEXCEPT {
- return node->is_sequence_container;
- }
- /**
- * @brief Checks whether a type refers to an associative container or not.
- * @return True if the type is an associative container, false otherwise.
- */
- [[nodiscard]] bool is_associative_container() const ENTT_NOEXCEPT {
- return node->is_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->template_info.is_template_specialization;
- }
- /**
- * @brief Returns the number of template arguments, if any.
- * @return The number of template arguments, if any.
- */
- [[nodiscard]] size_type template_arity() const ENTT_NOEXCEPT {
- return node->template_info.arity;
- }
- /**
- * @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 is_template_specialization() ? node->template_info.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(size_type index) const ENTT_NOEXCEPT {
- return index < template_arity() ? node->template_info.arg(index) : meta_type{};
- }
- /**
- * @brief Provides the number of dimensions of an array type.
- * @return The number of dimensions in case of array types, 0 otherwise.
- */
- [[nodiscard]] size_type rank() const ENTT_NOEXCEPT {
- return node->rank;
- }
- /**
- * @brief The number of elements along the given dimension of an array type.
- * @param dim The dimension of which to return the number of elements.
- * @return The number of elements along the given dimension in case of array
- * types, 0 otherwise.
- */
- [[nodiscard]] size_type extent(size_type dim = {}) const ENTT_NOEXCEPT {
- return node->extent(dim);
- }
- /**
- * @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 Provides the type for which the array is defined.
- * @return The type for which the array is defined or this type if it
- * doesn't refer to an array type.
- */
- [[nodiscard]] meta_type remove_extent() const ENTT_NOEXCEPT {
- return node->remove_extent();
- }
- /**
- * @brief Returns a range to use to visit top-level base meta types.
- * @return An iterable range to use to visit top-level base meta types.
- */
- [[nodiscard]] meta_range<meta_type, internal::meta_base_node> base() const ENTT_NOEXCEPT {
- return node->base;
- }
- /**
- * @brief Returns the base meta type associated with a given identifier.
- * @param id Unique identifier.
- * @return The base meta type associated with the given identifier, if any.
- */
- [[nodiscard]] meta_type base(const id_type id) const {
- return internal::meta_visit<&node_type::base>([id](const auto *curr) { return curr->type()->id == id; }, node);
- }
- /**
- * @brief Returns a range to use to visit top-level constructors.
- * @return An iterable range to use to visit top-level constructors.
- */
- [[nodiscard]] meta_range<meta_ctor> ctor() const ENTT_NOEXCEPT {
- return node->ctor;
- }
- /**
- * @brief Returns a constructor for a given list of types of arguments.
- * @tparam Args Constructor arguments.
- * @return The requested constructor, if any.
- */
- template<typename... Args>
- [[nodiscard]] meta_ctor ctor() const {
- return ctor<Args...>(node->ctor, std::make_index_sequence<sizeof...(Args)>{});
- }
- /**
- * @brief Returns a range to use to visit top-level data.
- * @return An iterable range to use to visit top-level data.
- */
- [[nodiscard]] meta_range<meta_data> data() const ENTT_NOEXCEPT {
- return node->data;
- }
- /**
- * @brief Returns the data associated with a given identifier.
- *
- * The data of the base classes will also be visited, if any.
- *
- * @param id Unique identifier.
- * @return The data associated with the given identifier, if any.
- */
- [[nodiscard]] meta_data data(const id_type id) const {
- return internal::meta_visit<&node_type::data>([id](const auto *curr) { return curr->id == id; }, node);
- }
- /**
- * @brief Returns a range to use to visit top-level functions.
- * @return An iterable range to use to visit top-level functions.
- */
- [[nodiscard]] meta_range<meta_func> func() const ENTT_NOEXCEPT {
- return node->func;
- }
- /**
- * @brief Returns the function associated with a given identifier.
- *
- * The functions of the base classes will also be visited, if any.<br/>
- * In the case of overloaded functions, the first one with the required
- * identifier will be returned.
- *
- * @param id Unique identifier.
- * @return The function associated with the given identifier, if any.
- */
- [[nodiscard]] meta_func func(const id_type id) const {
- return internal::meta_visit<&node_type::func>([id](const auto *curr) { return curr->id == id; }, node);
- }
- /**
- * @brief Creates an instance of the underlying type, if possible.
- *
- * Parameters must be such that a cast or conversion to the required types
- * is possible. Otherwise, an empty and thus invalid wrapper is returned.
- *
- * @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 {
- meta_any ret{};
- internal::meta_visit<&node_type::ctor>([args, sz, &ret](const auto *curr) { return (curr->arity == sz) && (ret = curr->invoke(args)); }, node);
- return ret;
- }
- /**
- * @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. Otherwise, invoking the underlying function results in an
- * undefined behavior.
- *
- * @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 internal::meta_func_node* candidate{};
- size_type extent{sz + 1u};
- bool ambiguous{};
- for(auto *it = internal::meta_visit<&node_type::func>([id, sz](const auto *curr) { return curr->id == id && curr->arity == sz; }, node); it && it->id == id && it->arity == sz; it = it->next) {
- size_type direct{};
- size_type ext{};
- for(size_type next{}; next < sz && next == (direct + ext); ++next) {
- const auto type = args[next].type();
- const auto req = it->arg(next).info();
- type.info() == req ? ++direct : (ext += can_cast_or_convert(type.node, req));
- }
- if((direct + ext) == sz) {
- if(ext < extent) {
- candidate = it;
- extent = ext;
- ambiguous = false;
- } else if(ext == extent) {
- ambiguous = true;
- }
- }
- }
- return (candidate && !ambiguous) ? 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. Otherwise, invoking the setter results in an undefined
- * behavior.<br/>
- * The type of the value must be 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. Otherwise, invoking the getter results in an undefined behavior.
- *
- * @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 use to visit top-level properties.
- * @return An iterable range to use to visit top-level properties.
- */
- [[nodiscard]] meta_range<meta_prop> prop() const ENTT_NOEXCEPT {
- return node->prop;
- }
- /**
- * @brief Returns the property associated with a given key.
- *
- * Properties of the base classes will also be visited, if any.
- *
- * @param key The key to use to search for a property.
- * @return The property associated with the given key, if any.
- */
- [[nodiscard]] meta_prop prop(meta_any key) const {
- return internal::meta_visit<&node_type::prop>([&key](const auto *curr) { return curr->id == 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);
- }
- /**
- * @brief Resets a type and all its parts.
- *
- * This function 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.
- */
- void reset() ENTT_NOEXCEPT {
- for(auto** it = internal::meta_context::global(); *it; it = &(*it)->next) {
- if(*it == node) {
- *it = (*it)->next;
- break;
- }
- }
- unregister_all(&node->prop);
- unregister_all(&node->base);
- unregister_all(&node->conv);
- unregister_all<&internal::meta_ctor_node::prop>(&node->ctor);
- unregister_all<&internal::meta_data_node::prop>(&node->data);
- unregister_all<&internal::meta_func_node::prop>(&node->func);
- node->id = {};
- node->ctor = node->def_ctor;
- node->dtor = nullptr;
- }
- private:
- 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_type meta_ctor::parent() const ENTT_NOEXCEPT {
- return node->parent;
- }
- [[nodiscard]] inline meta_type meta_ctor::arg(size_type index) const ENTT_NOEXCEPT {
- return index < arity() ? node->arg(index) : meta_type{};
- }
- [[nodiscard]] inline meta_type meta_data::parent() const ENTT_NOEXCEPT {
- return node->parent;
- }
- [[nodiscard]] inline meta_type meta_data::type() const ENTT_NOEXCEPT {
- return node->type();
- }
- [[nodiscard]] inline meta_type meta_func::parent() const ENTT_NOEXCEPT {
- return node->parent;
- }
- [[nodiscard]] inline meta_type meta_func::ret() const ENTT_NOEXCEPT {
- return node->ret();
- }
- [[nodiscard]] inline meta_type meta_func::arg(size_type index) const ENTT_NOEXCEPT {
- return index < arity() ? node->arg(index) : meta_type{};
- }
- /*! @brief Opaque iterator for sequence containers. */
- class meta_sequence_container::meta_iterator {
- /*! @brief A sequence container can access the underlying iterator. */
- friend class meta_sequence_container;
- enum class operation { INCR, DEREF };
- using vtable_type = void(const operation, const any &, void *);
- template<typename It>
- static void basic_vtable(const operation op, const any &from, void *to) {
- switch(op) {
- case operation::INCR:
- ++any_cast<It &>(const_cast<any &>(from));
- break;
- case operation::DEREF:
- static_cast<meta_any *>(to)->emplace<typename std::iterator_traits<It>::reference>(*any_cast<const It &>(from));
- break;
- }
- }
- public:
- /*! @brief Signed integer type. */
- using difference_type = std::ptrdiff_t;
- /*! @brief Type of elements returned by the iterator. */
- using value_type = meta_any;
- /*! @brief Pointer type, `void` on purpose. */
- using pointer = void;
- /*! @brief Reference type, it is **not** an actual reference. */
- using reference = value_type;
- /*! @brief Iterator category. */
- using iterator_category = std::input_iterator_tag;
- /*! @brief Default constructor. */
- meta_iterator() ENTT_NOEXCEPT = default;
- /**
- * @brief Constructs a meta iterator from a given iterator.
- * @tparam It Type of actual iterator with which to build the meta iterator.
- * @param iter The actual iterator with which to build the meta iterator.
- */
- template<typename It>
- meta_iterator(It iter)
- : vtable{&basic_vtable<It>},
- handle{std::move(iter)}
- {}
- /*! @brief Pre-increment operator. @return This iterator. */
- meta_iterator & operator++() ENTT_NOEXCEPT {
- return vtable(operation::INCR, handle, nullptr), *this;
- }
- /*! @brief Post-increment operator. @return This iterator. */
- meta_iterator operator++(int) ENTT_NOEXCEPT {
- meta_iterator orig = *this;
- return ++(*this), orig;
- }
- /**
- * @brief Checks if two iterators refer to the same element.
- * @param other The iterator with which to compare.
- * @return True if the iterators refer to the same element, false otherwise.
- */
- [[nodiscard]] bool operator==(const meta_iterator &other) const ENTT_NOEXCEPT {
- return handle == other.handle;
- }
- /**
- * @brief Checks if two iterators refer to the same element.
- * @param other The iterator with which to compare.
- * @return False if the iterators refer to the same element, true otherwise.
- */
- [[nodiscard]] bool operator!=(const meta_iterator &other) const ENTT_NOEXCEPT {
- return !(*this == other);
- }
- /**
- * @brief Indirection operator.
- * @return The element to which the iterator points.
- */
- [[nodiscard]] reference operator*() const {
- meta_any other;
- vtable(operation::DEREF, handle, &other);
- return other;
- }
- /**
- * @brief Returns false if an iterator is invalid, true otherwise.
- * @return False if the iterator is invalid, true otherwise.
- */
- [[nodiscard]] explicit operator bool() const ENTT_NOEXCEPT {
- return static_cast<bool>(handle);
- }
- private:
- vtable_type *vtable{};
- any handle{};
- };
- template<typename Type>
- struct meta_sequence_container::meta_sequence_container_proxy {
- using traits_type = meta_sequence_container_traits<Type>;
- [[nodiscard]] static meta_type value_type() ENTT_NOEXCEPT {
- return internal::meta_info<typename Type::value_type>::resolve();
- }
- [[nodiscard]] static size_type size(const any &container) ENTT_NOEXCEPT {
- return traits_type::size(any_cast<const Type &>(container));
- }
- [[nodiscard]] static bool resize(any &container, size_type sz) {
- auto * const cont = any_cast<Type>(&container);
- return cont && traits_type::resize(*cont, sz);
- }
- [[nodiscard]] static bool clear(any &container) {
- auto * const cont = any_cast<Type>(&container);
- return cont && traits_type::clear(*cont);
- }
- [[nodiscard]] static iterator begin(any &container) {
- if(auto * const cont = any_cast<Type>(&container); cont) {
- return iterator{traits_type::begin(*cont)};
- }
- return iterator{traits_type::cbegin(any_cast<const Type &>(container))};
- }
- [[nodiscard]] static iterator end(any &container) {
- if(auto * const cont = any_cast<Type>(&container); cont) {
- return iterator{traits_type::end(*cont)};
- }
- return iterator{traits_type::cend(any_cast<const Type &>(container))};
- }
- [[nodiscard]] static std::pair<iterator, bool> insert(any &container, iterator it, meta_any &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>>();
- auto ret = traits_type::insert(*cont, any_cast<const typename Type::iterator &>(it.handle), element ? *element : value.cast<typename Type::value_type>());
- return { iterator{std::move(ret.first)}, ret.second };
- }
- }
- return {};
- }
- [[nodiscard]] static std::pair<iterator, bool> erase(any &container, iterator it) {
- if(auto * const cont = any_cast<Type>(&container); cont) {
- auto ret = traits_type::erase(*cont, any_cast<const typename Type::iterator &>(it.handle));
- return { iterator{std::move(ret.first)}, ret.second };
- }
- return {};
- }
- [[nodiscard]] static meta_any get(any &container, size_type pos) {
- if(auto * const cont = any_cast<Type>(&container); cont) {
- return meta_any{std::in_place_type<typename Type::reference>, traits_type::get(*cont, pos)};
- }
- return meta_any{std::in_place_type<typename Type::const_reference>, traits_type::cget(any_cast<const Type &>(container), pos)};
- }
- };
- /**
- * @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_fn();
- }
- /**
- * @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(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 clear_fn(storage);
- }
- /**
- * @brief Returns an iterator to the first element of a container.
- * @return An iterator to the first element of the container.
- */
- [[nodiscard]] inline meta_sequence_container::iterator meta_sequence_container::begin() {
- return begin_fn(storage);
- }
- /**
- * @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 end_fn(storage);
- }
- /**
- * @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 pair consisting of an iterator to the inserted element (in case of
- * success) and a bool denoting whether the insertion took place.
- */
- inline std::pair<meta_sequence_container::iterator, bool> meta_sequence_container::insert(iterator it, meta_any value) {
- return insert_fn(storage, it, value);
- }
- /**
- * @brief Removes a given element from a container.
- * @param it Iterator to the element to remove.
- * @return A pair consisting of an iterator following the last removed element
- * (in case of success) and a bool denoting whether the insertion took place.
- */
- inline std::pair<meta_sequence_container::iterator, bool> meta_sequence_container::erase(iterator it) {
- return erase_fn(storage, it);
- }
- /**
- * @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[](size_type pos) {
- return get_fn(storage, pos);
- }
- /**
- * @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 Opaque iterator for associative containers. */
- class meta_associative_container::meta_iterator {
- enum operation { INCR, DEREF };
- using vtable_type = void(const operation, const any &, void *);
- template<bool KeyOnly, typename It>
- static void basic_vtable(const operation op, const any &from, void *to) {
- switch(op) {
- case operation::INCR:
- ++any_cast<It &>(const_cast<any &>(from));
- break;
- case operation::DEREF:
- const auto &it = any_cast<const It &>(from);
- if constexpr(KeyOnly) {
- static_cast<std::pair<meta_any, meta_any> *>(to)->first.emplace<decltype(*it)>(*it);
- } else {
- static_cast<std::pair<meta_any, meta_any> *>(to)->first.emplace<decltype((it->first))>(it->first);
- static_cast<std::pair<meta_any, meta_any> *>(to)->second.emplace<decltype((it->second))>(it->second);
- }
- break;
- }
- }
- public:
- /*! @brief Signed integer type. */
- using difference_type = std::ptrdiff_t;
- /*! @brief Type of elements returned by the iterator. */
- using value_type = std::pair<meta_any, meta_any>;
- /*! @brief Pointer type, `void` on purpose. */
- using pointer = void;
- /*! @brief Reference type, it is **not** an actual reference. */
- using reference = value_type;
- /*! @brief Iterator category. */
- using iterator_category = std::input_iterator_tag;
- /*! @brief Default constructor. */
- meta_iterator() ENTT_NOEXCEPT = default;
- /**
- * @brief Constructs an meta iterator from a given iterator.
- * @tparam KeyOnly True if the container is also key-only, false otherwise.
- * @tparam It Type of actual iterator with which to build the meta iterator.
- * @param iter The actual iterator with which to build the meta iterator.
- */
- template<bool KeyOnly, typename It>
- meta_iterator(std::integral_constant<bool, KeyOnly>, It iter)
- : vtable{&basic_vtable<KeyOnly, It>},
- handle{std::move(iter)}
- {}
- /*! @brief Pre-increment operator. @return This iterator. */
- meta_iterator & operator++() ENTT_NOEXCEPT {
- return vtable(operation::INCR, handle, nullptr), *this;
- }
- /*! @brief Post-increment operator. @return This iterator. */
- meta_iterator operator++(int) ENTT_NOEXCEPT {
- meta_iterator orig = *this;
- return ++(*this), orig;
- }
- /**
- * @brief Checks if two iterators refer to the same element.
- * @param other The iterator with which to compare.
- * @return True if the iterators refer to the same element, false otherwise.
- */
- [[nodiscard]] bool operator==(const meta_iterator &other) const ENTT_NOEXCEPT {
- return handle == other.handle;
- }
- /**
- * @brief Checks if two iterators refer to the same element.
- * @param other The iterator with which to compare.
- * @return False if the iterators refer to the same element, true otherwise.
- */
- [[nodiscard]] bool operator!=(const meta_iterator &other) const ENTT_NOEXCEPT {
- return !(*this == other);
- }
- /**
- * @brief Indirection operator.
- * @return The element to which the iterator points.
- */
- [[nodiscard]] reference operator*() const {
- reference other;
- vtable(operation::DEREF, handle, &other);
- return other;
- }
- /**
- * @brief Returns false if an iterator is invalid, true otherwise.
- * @return False if the iterator is invalid, true otherwise.
- */
- [[nodiscard]] explicit operator bool() const ENTT_NOEXCEPT {
- return static_cast<bool>(handle);
- }
- private:
- vtable_type *vtable{};
- any handle{};
- };
- template<typename Type>
- struct meta_associative_container::meta_associative_container_proxy {
- using traits_type = meta_associative_container_traits<Type>;
- [[nodiscard]] static meta_type key_type() ENTT_NOEXCEPT {
- return internal::meta_info<typename Type::key_type>::resolve();
- }
- [[nodiscard]] static meta_type mapped_type() ENTT_NOEXCEPT {
- if constexpr(is_key_only_meta_associative_container_v<Type>) {
- return meta_type{};
- } else {
- return internal::meta_info<typename Type::mapped_type>::resolve();
- }
- }
- [[nodiscard]] static meta_type value_type() ENTT_NOEXCEPT {
- return internal::meta_info<typename Type::value_type>::resolve();
- }
- [[nodiscard]] static size_type size(const any &container) ENTT_NOEXCEPT {
- return traits_type::size(any_cast<const Type &>(container));
- }
- [[nodiscard]] static bool clear(any &container) {
- auto * const cont = any_cast<Type>(&container);
- return cont && traits_type::clear(*cont);
- }
- [[nodiscard]] static iterator begin(any &container) {
- if(auto * const cont = any_cast<Type>(&container); cont) {
- return iterator{is_key_only_meta_associative_container<Type>{}, traits_type::begin(*cont)};
- }
- return iterator{is_key_only_meta_associative_container<Type>{}, traits_type::cbegin(any_cast<const Type &>(container))};
- }
- [[nodiscard]] static iterator end(any &container) {
- if(auto * const cont = any_cast<Type>(&container); cont) {
- return iterator{is_key_only_meta_associative_container<Type>{}, traits_type::end(*cont)};
- }
- return iterator{is_key_only_meta_associative_container<Type>{}, traits_type::cend(any_cast<const Type &>(container))};
- }
- [[nodiscard]] static bool insert(any &container, meta_any &key, meta_any &value) {
- if(auto * const cont = any_cast<Type>(&container); cont && key.allow_cast<const typename Type::key_type &>()) {
- if constexpr(is_key_only_meta_associative_container_v<Type>) {
- return traits_type::insert(*cont, key.cast<const typename Type::key_type &>());
- } else {
- return value.allow_cast<const typename Type::mapped_type &>()
- && traits_type::insert(*cont, key.cast<const typename Type::key_type &>(), value.cast<const typename Type::mapped_type &>());
- }
- }
- return false;
- }
- [[nodiscard]] static bool erase(any &container, meta_any &key) {
- if(auto * const cont = any_cast<Type>(&container); cont && key.allow_cast<const typename Type::key_type &>()) {
- return traits_type::erase(*cont, key.cast<const typename Type::key_type &>());
- }
- return false;
- }
- [[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{is_key_only_meta_associative_container<Type>{}, traits_type::find(*cont, key.cast<const typename Type::key_type &>())};
- }
- return iterator{is_key_only_meta_associative_container<Type>{}, traits_type::cfind(any_cast<const Type &>(container), key.cast<const typename Type::key_type &>())};
- }
- return {};
- }
- };
- /**
- * @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_fn();
- }
- /**
- * @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_fn();
- }
- /*! @copydoc meta_sequence_container::value_type */
- [[nodiscard]] inline meta_type meta_associative_container::value_type() const ENTT_NOEXCEPT {
- return value_type_fn();
- }
- /*! @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 begin_fn(storage);
- }
- /*! @copydoc meta_sequence_container::end */
- [[nodiscard]] inline meta_associative_container::iterator meta_associative_container::end() {
- return end_fn(storage);
- }
- /**
- * @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);
- }
- }
- #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/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 {
- struct meta_type_node;
- struct meta_prop_node {
- meta_prop_node * next;
- const meta_any &id;
- meta_any &value;
- };
- struct meta_base_node {
- meta_type_node * const parent;
- meta_base_node * next;
- meta_type_node *(* const type)() ENTT_NOEXCEPT;
- const void *(* const cast)(const void *) ENTT_NOEXCEPT;
- };
- struct meta_conv_node {
- meta_type_node * const parent;
- meta_conv_node * next;
- meta_type_node *(* const type)() ENTT_NOEXCEPT;
- meta_any(* const conv)(const void *);
- };
- struct meta_ctor_node {
- using size_type = std::size_t;
- meta_type_node * const parent;
- meta_ctor_node * next;
- meta_prop_node * prop;
- const size_type arity;
- meta_type(* const arg)(const size_type) ENTT_NOEXCEPT;
- meta_any(* const invoke)(meta_any * const);
- };
- struct meta_data_node {
- id_type id;
- meta_type_node * const parent;
- meta_data_node * next;
- meta_prop_node * prop;
- const bool is_const;
- const bool is_static;
- meta_type_node *(* const 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;
- meta_type_node * const parent;
- meta_func_node * next;
- meta_prop_node * prop;
- const size_type arity;
- const bool is_const;
- const bool is_static;
- meta_type_node *(* const ret)() ENTT_NOEXCEPT;
- meta_type(* const arg)(const size_type) ENTT_NOEXCEPT;
- meta_any(* const invoke)(meta_handle, meta_any *);
- };
- struct meta_template_info {
- using size_type = std::size_t;
- const bool is_template_specialization;
- const size_type arity;
- meta_type_node *(* const type)() ENTT_NOEXCEPT;
- 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;
- meta_type_node * next;
- meta_prop_node * prop;
- const size_type size_of;
- const bool is_void;
- const bool is_integral;
- const bool is_floating_point;
- const bool is_array;
- const bool is_enum;
- const bool is_union;
- const bool is_class;
- const bool is_pointer;
- const bool is_function_pointer;
- const bool is_member_object_pointer;
- const bool is_member_function_pointer;
- const bool is_pointer_like;
- const bool is_sequence_container;
- const bool is_associative_container;
- const meta_template_info template_info;
- const size_type rank;
- size_type(* const extent)(const size_type) ENTT_NOEXCEPT ;
- meta_type_node *(* const remove_pointer)() ENTT_NOEXCEPT;
- meta_type_node *(* const remove_extent)() ENTT_NOEXCEPT;
- meta_ctor_node * const def_ctor;
- 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<auto Member, typename Op, typename Node>
- auto meta_visit(const Op &op, const Node *node)
- -> std::decay_t<decltype(node->*Member)> {
- for(auto *curr = node->*Member; curr; curr = curr->next) {
- if(op(curr)) {
- return curr;
- }
- }
- if constexpr(std::is_same_v<Node, meta_type_node>) {
- for(auto *curr = node->base; curr; curr = curr->next) {
- if(auto *ret = meta_visit<Member>(op, curr->type()); ret) {
- return ret;
- }
- }
- }
- return 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");
- template<std::size_t... Index>
- [[nodiscard]] static auto extent(const meta_type_node::size_type dim, std::index_sequence<Index...>) ENTT_NOEXCEPT {
- meta_type_node::size_type ext{};
- ((ext = (dim == Index ? std::extent_v<Type, Index> : ext)), ...);
- return ext;
- }
- [[nodiscard]] static meta_ctor_node * meta_default_constructor([[maybe_unused]] meta_type_node *type) ENTT_NOEXCEPT {
- if constexpr(std::is_default_constructible_v<Type>) {
- static meta_ctor_node node{
- type,
- nullptr,
- nullptr,
- 0u,
- nullptr,
- [](meta_any * const) { return meta_any{std::in_place_type<Type>}; }
- };
- return &node;
- } else {
- return nullptr;
- }
- }
- [[nodiscard]] static meta_template_info meta_template_descriptor() ENTT_NOEXCEPT {
- if constexpr(is_complete_v<meta_template_traits<Type>>) {
- return {
- true,
- 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);
- }
- };
- } else {
- return { false, 0u, nullptr, nullptr };
- }
- }
- public:
- [[nodiscard]] static meta_type_node * resolve() ENTT_NOEXCEPT {
- static meta_type_node node{
- type_id<Type>(),
- {},
- nullptr,
- nullptr,
- size_of_v<Type>,
- std::is_void_v<Type>,
- std::is_integral_v<Type>,
- std::is_floating_point_v<Type>,
- std::is_array_v<Type>,
- std::is_enum_v<Type>,
- std::is_union_v<Type>,
- std::is_class_v<Type>,
- std::is_pointer_v<Type>,
- std::is_pointer_v<Type> && std::is_function_v<std::remove_pointer_t<Type>>,
- std::is_member_object_pointer_v<Type>,
- std::is_member_function_pointer_v<Type>,
- is_meta_pointer_like_v<Type>,
- is_complete_v<meta_sequence_container_traits<Type>>,
- is_complete_v<meta_associative_container_traits<Type>>,
- meta_template_descriptor(),
- std::rank_v<Type>,
- [](meta_type_node::size_type dim) ENTT_NOEXCEPT { return extent(dim, std::make_index_sequence<std::rank_v<Type>>{}); },
- &meta_node<std::remove_cv_t<std::remove_reference_t<std::remove_pointer_t<Type>>>>::resolve,
- &meta_node<std::remove_cv_t<std::remove_reference_t<std::remove_extent_t<Type>>>>::resolve,
- meta_default_constructor(&node),
- meta_default_constructor(&node)
- };
- return &node;
- }
- };
- template<typename Type>
- struct meta_info: meta_node<std::remove_cv_t<std::remove_reference_t<Type>>> {};
- template<typename... Args>
- 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_info<Args>::resolve()...};
- return args[index + 1u];
- }
- }
- /**
- * Internal details not to be documented.
- * @endcond
- */
- }
- #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
- {};
- }
- #endif
- // #include "meta/policy.hpp"
- #ifndef ENTT_META_POLICY_HPP
- #define ENTT_META_POLICY_HPP
- namespace entt {
- /*! @brief Empty class type used to request the _as ref_ policy. */
- struct as_ref_t {};
- /*! @brief Empty class type used to request the _as cref_ policy. */
- struct as_cref_t {};
- /*! @brief Empty class type used to request the _as-is_ policy. */
- struct as_is_t {};
- /*! @brief Empty class type used to request the _as void_ policy. */
- struct as_void_t {};
- }
- #endif
- // #include "meta/range.hpp"
- #ifndef ENTT_META_RANGE_HPP
- #define ENTT_META_RANGE_HPP
- #include <cstddef>
- #include <iterator>
- namespace entt {
- /**
- * @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>
- class meta_range {
- struct range_iterator {
- using difference_type = std::ptrdiff_t;
- using value_type = Type;
- using pointer = void;
- using reference = value_type;
- using iterator_category = std::input_iterator_tag;
- using node_type = Node;
- range_iterator() ENTT_NOEXCEPT = default;
- range_iterator(node_type *head) ENTT_NOEXCEPT
- : it{head}
- {}
- range_iterator & operator++() ENTT_NOEXCEPT {
- return (it = it->next), *this;
- }
- range_iterator operator++(int) ENTT_NOEXCEPT {
- range_iterator orig = *this;
- return ++(*this), orig;
- }
- [[nodiscard]] reference operator*() const ENTT_NOEXCEPT {
- return it;
- }
- [[nodiscard]] bool operator==(const range_iterator &other) const ENTT_NOEXCEPT {
- return other.it == it;
- }
- [[nodiscard]] bool operator!=(const range_iterator &other) const ENTT_NOEXCEPT {
- return !(*this == other);
- }
- private:
- node_type *it{};
- };
- public:
- /*! @brief Node type. */
- using node_type = Node;
- /*! @brief Input iterator type. */
- using iterator = range_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)
- : node{head}
- {}
- /**
- * @brief Returns an iterator to the beginning.
- * @return An iterator to the first meta object of the range.
- */
- [[nodiscard]] iterator begin() const ENTT_NOEXCEPT {
- return iterator{node};
- }
- /**
- * @brief Returns an iterator to the end.
- * @return An iterator to the element following the last meta object of the
- * range.
- */
- [[nodiscard]] iterator end() const ENTT_NOEXCEPT {
- return iterator{};
- }
- private:
- node_type *node{nullptr};
- };
- }
- #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_info<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() {
- 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 = *internal::meta_context::global(); curr; curr = curr->next) {
- if(curr->id == id) {
- return curr;
- }
- }
- return {};
- }
- /**
- * @brief Returns the meta type associated with a given type info object, if
- * any.
- * @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 = *internal::meta_context::global(); curr; curr = curr->next) {
- if(curr->info == info) {
- return curr;
- }
- }
- return {};
- }
- }
- #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...> typename>
- 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...> typename 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...>;
- };
- }
- #endif
- // #include "meta/type_traits.hpp"
- #ifndef ENTT_META_TYPE_TRAITS_HPP
- #define ENTT_META_TYPE_TRAITS_HPP
- #include <type_traits>
- 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 meta associative
- * container claims to wrap a key-only type, false otherwise.
- * @tparam Type Potentially key-only meta associative container type.
- */
- template<typename, typename = void>
- struct is_key_only_meta_associative_container: std::true_type {};
- /*! @copydoc is_key_only_meta_associative_container */
- template<typename Type>
- struct is_key_only_meta_associative_container<Type, std::void_t<typename meta_associative_container_traits<Type>::type::mapped_type>>
- : std::false_type
- {};
- /**
- * @brief Helper variable template.
- * @tparam Type Potentially key-only meta associative container type.
- */
- template<typename Type>
- inline constexpr auto is_key_only_meta_associative_container_v = is_key_only_meta_associative_container<Type>::value;
- /**
- * @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;
- }
- #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_same_v<Type, Class>, 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_same_v<Type, Class>;
- };
- /**
- * @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_same_v<Type, Class>, 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_same_v<Type, Class>;
- };
- /**
- * @brief Meta function descriptor.
- * @tparam Type Reflected type to which the meta function is associated.
- * @tparam Ret Function return type.
- * @tparam Args Function arguments.
- */
- template<typename Type, typename Ret, typename... Args>
- struct meta_function_descriptor<Type, Ret(*)(Args...)> {
- /*! @brief Meta function return type. */
- using return_type = Ret;
- /*! @brief Meta function arguments. */
- using args_type = type_list<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 = 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... Args>
- static constexpr meta_function_descriptor<Type, Ret(*)(Args...)> get_rid_of_noexcept(Ret(*)(Args...));
- 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 Returns the meta type of the i-th element of a list of arguments.
- * @tparam Args Actual types of arguments.
- * @return The meta type of the i-th element of the list of arguments.
- */
- template<typename... Args>
- [[nodiscard]] static meta_type meta_arg(type_list<Args...>, const std::size_t index) ENTT_NOEXCEPT {
- return internal::meta_arg_node(type_list<Args...>{}, index);
- }
- /**
- * @brief Constructs an instance given a list of erased parameters, if possible.
- * @tparam Type Actual type of the instance to construct.
- * @tparam Args Types of arguments expected.
- * @tparam Index Indexes to use to extract erased arguments from their list.
- * @param args Parameters to use to construct the instance.
- * @return A meta any containing the new instance, if 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 Type{(args+Index)->cast<Args>()...};
- }
- return {};
- }
- /**
- * @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_function_v<std::remove_reference_t<std::remove_pointer_t<decltype(Data)>>>) {
- using data_type = type_list_element_t<1u, typename meta_function_helper_t<Type, decltype(Data)>::args_type>;
- if(auto * const clazz = instance->try_cast<Type>(); clazz && value.allow_cast<data_type>()) {
- Data(*clazz, value.cast<data_type>());
- return true;
- }
- } else if constexpr(std::is_member_function_pointer_v<decltype(Data)>) {
- using data_type = type_list_element_t<0u, typename meta_function_helper_t<Type, decltype(Data)>::args_type>;
- if(auto * const clazz = instance->try_cast<Type>(); clazz && value.allow_cast<data_type>()) {
- (clazz->*Data)(value.cast<data_type>());
- return true;
- }
- } else if constexpr(std::is_member_object_pointer_v<decltype(Data)>) {
- using data_type = std::remove_reference_t<decltype(std::declval<Type>().*Data)>;
- 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>()) {
- clazz->*Data = 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 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.
- */
- template<typename Policy = as_is_t, typename Type>
- meta_any meta_dispatch(Type &&value) {
- if constexpr(std::is_same_v<Policy, as_void_t>) {
- return meta_any{std::in_place_type<void>, std::forward<Type>(value)};
- } 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 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_function_v<std::remove_reference_t<std::remove_pointer_t<decltype(Data)>>>) {
- auto * const clazz = instance->try_cast<std::conditional_t<std::is_invocable_v<decltype(Data), const Type &>, const Type, Type>>();
- return clazz ? meta_dispatch<Policy>(Data(*clazz)) : meta_any{};
- } else if constexpr(std::is_member_function_pointer_v<decltype(Data)>) {
- auto * const clazz = instance->try_cast<std::conditional_t<std::is_invocable_v<decltype(Data), const Type &>, const Type, Type>>();
- return clazz ? meta_dispatch<Policy>((clazz->*Data)()) : meta_any{};
- } else if constexpr(std::is_member_object_pointer_v<decltype(Data)>) {
- if constexpr(!std::is_array_v<std::remove_cv_t<std::remove_reference_t<decltype(std::declval<Type>().*Data)>>>) {
- if(auto * clazz = instance->try_cast<Type>(); clazz) {
- return meta_dispatch<Policy>(clazz->*Data);
- } else if(auto * fallback = instance->try_cast<const Type>(); fallback) {
- return meta_dispatch<Policy>(fallback->*Data);
- }
- }
- 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);
- }
- }
- /**
- * @brief Invokes a function given a list of erased parameters, if possible.
- * @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).
- * @tparam Index Indexes to use to extract erased arguments from their list.
- * @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, std::size_t... Index>
- [[nodiscard]] std::enable_if_t<!std::is_invocable_v<decltype(Candidate)>, meta_any> meta_invoke([[maybe_unused]] meta_handle instance, meta_any *args, std::index_sequence<Index...>) {
- using descriptor = meta_function_helper_t<Type, decltype(Candidate)>;
- const auto invoke = [](auto &&maybe_clazz, auto &&... other) {
- if constexpr(std::is_member_function_pointer_v<decltype(Candidate)>) {
- if constexpr(std::is_void_v<typename descriptor::return_type>) {
- (std::forward<decltype(maybe_clazz)>(maybe_clazz).*Candidate)(std::forward<decltype(other)>(other)...);
- return meta_any{std::in_place_type<void>};
- } else {
- return meta_dispatch<Policy>((std::forward<decltype(maybe_clazz)>(maybe_clazz).*Candidate)(std::forward<decltype(other)>(other)...));
- }
- } else {
- if constexpr(std::is_void_v<typename descriptor::return_type>) {
- Candidate(std::forward<decltype(maybe_clazz)>(maybe_clazz), std::forward<decltype(other)>(other)...);
- return meta_any{std::in_place_type<void>};
- } else {
- return meta_dispatch<Policy>(Candidate(std::forward<decltype(maybe_clazz)>(maybe_clazz), std::forward<decltype(other)>(other)...));
- }
- }
- };
- if constexpr(std::is_invocable_v<decltype(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 invoke(*clazz, (args+Index)->cast<type_list_element_t<Index, typename descriptor::args_type>>()...);
- }
- } else if constexpr(std::is_invocable_v<decltype(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 invoke(*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 invoke((args+Index)->cast<type_list_element_t<Index, typename descriptor::args_type>>()...);
- }
- }
- return meta_any{};
- }
- /**
- * @brief Invokes a function given a list of erased parameters, if possible.
- * @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).
- * @tparam Index Indexes to use to extract erased arguments from their list.
- * @return A meta any containing the returned value, if any.
- */
- template<typename Type, auto Candidate, typename Policy = as_is_t, std::size_t... Index>
- [[nodiscard]] std::enable_if_t<std::is_invocable_v<decltype(Candidate)>, meta_any> meta_invoke(meta_handle, meta_any *, std::index_sequence<Index...>) {
- if constexpr(std::is_void_v<decltype(Candidate())>) {
- Candidate();
- return meta_any{std::in_place_type<void>};
- } else {
- return meta_dispatch<Policy>(Candidate());
- }
- }
- }
- #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(...);
- }
- 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;
- }
- #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
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_NOEXCEPT noexcept
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_NOEXCEPT
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606L
- # include <new>
- # define ENTT_LAUNDER(expr) std::launder(expr)
- #else
- # define ENTT_LAUNDER(expr) expr
- #endif
- #ifndef ENTT_USE_ATOMIC
- # define ENTT_MAYBE_ATOMIC(Type) Type
- #else
- # include <atomic>
- # define ENTT_MAYBE_ATOMIC(Type) std::atomic<Type>
- #endif
- #ifndef ENTT_ID_TYPE
- # include <cstdint>
- # define ENTT_ID_TYPE std::uint32_t
- #endif
- #ifdef ENTT_SPARSE_PAGE
- static_assert(ENTT_SPARSE_PAGE && ((ENTT_SPARSE_PAGE & (ENTT_SPARSE_PAGE - 1)) == 0), "ENTT_SPARSE_PAGE must be a power of two");
- #else
- # define ENTT_SPARSE_PAGE 4096
- #endif
- #ifdef ENTT_PACKED_PAGE
- static_assert(ENTT_PACKED_PAGE && ((ENTT_PACKED_PAGE & (ENTT_PACKED_PAGE - 1)) == 0), "ENTT_PACKED_PAGE must be a power of two");
- #else
- # 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
- # include <type_traits>
- # define ENTT_IGNORE_IF_EMPTY std::false_type
- #else
- # include <type_traits>
- # define ENTT_IGNORE_IF_EMPTY std::true_type
- #endif
- #ifndef ENTT_STANDARD_CPP
- # 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
- #endif
- // #include "../core/any.hpp"
- #ifndef ENTT_CORE_ANY_HPP
- #define ENTT_CORE_ANY_HPP
- #include <cstddef>
- #include <functional>
- #include <memory>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- #ifndef ENTT_CONFIG_CONFIG_H
- #define ENTT_CONFIG_CONFIG_H
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_NOEXCEPT noexcept
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_NOEXCEPT
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606L
- # include <new>
- # define ENTT_LAUNDER(expr) std::launder(expr)
- #else
- # define ENTT_LAUNDER(expr) expr
- #endif
- #ifndef ENTT_USE_ATOMIC
- # define ENTT_MAYBE_ATOMIC(Type) Type
- #else
- # include <atomic>
- # define ENTT_MAYBE_ATOMIC(Type) std::atomic<Type>
- #endif
- #ifndef ENTT_ID_TYPE
- # include <cstdint>
- # define ENTT_ID_TYPE std::uint32_t
- #endif
- #ifdef ENTT_SPARSE_PAGE
- static_assert(ENTT_SPARSE_PAGE && ((ENTT_SPARSE_PAGE & (ENTT_SPARSE_PAGE - 1)) == 0), "ENTT_SPARSE_PAGE must be a power of two");
- #else
- # define ENTT_SPARSE_PAGE 4096
- #endif
- #ifdef ENTT_PACKED_PAGE
- static_assert(ENTT_PACKED_PAGE && ((ENTT_PACKED_PAGE & (ENTT_PACKED_PAGE - 1)) == 0), "ENTT_PACKED_PAGE must be a power of two");
- #else
- # 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
- # include <type_traits>
- # define ENTT_IGNORE_IF_EMPTY std::false_type
- #else
- # include <type_traits>
- # define ENTT_IGNORE_IF_EMPTY std::true_type
- #endif
- #ifndef ENTT_STANDARD_CPP
- # 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
- #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
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_NOEXCEPT noexcept
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_NOEXCEPT
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606L
- # include <new>
- # define ENTT_LAUNDER(expr) std::launder(expr)
- #else
- # define ENTT_LAUNDER(expr) expr
- #endif
- #ifndef ENTT_USE_ATOMIC
- # define ENTT_MAYBE_ATOMIC(Type) Type
- #else
- # include <atomic>
- # define ENTT_MAYBE_ATOMIC(Type) std::atomic<Type>
- #endif
- #ifndef ENTT_ID_TYPE
- # include <cstdint>
- # define ENTT_ID_TYPE std::uint32_t
- #endif
- #ifdef ENTT_SPARSE_PAGE
- static_assert(ENTT_SPARSE_PAGE && ((ENTT_SPARSE_PAGE & (ENTT_SPARSE_PAGE - 1)) == 0), "ENTT_SPARSE_PAGE must be a power of two");
- #else
- # define ENTT_SPARSE_PAGE 4096
- #endif
- #ifdef ENTT_PACKED_PAGE
- static_assert(ENTT_PACKED_PAGE && ((ENTT_PACKED_PAGE & (ENTT_PACKED_PAGE - 1)) == 0), "ENTT_PACKED_PAGE must be a power of two");
- #else
- # 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
- # include <type_traits>
- # define ENTT_IGNORE_IF_EMPTY std::false_type
- #else
- # include <type_traits>
- # define ENTT_IGNORE_IF_EMPTY std::true_type
- #endif
- #ifndef ENTT_STANDARD_CPP
- # 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
- #endif
- namespace entt {
- /*! @brief Identity function object (waiting for C++20). */
- struct identity {
- /**
- * @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;
- };
- }
- #endif
- // #include "fwd.hpp"
- #ifndef ENTT_CORE_FWD_HPP
- #define ENTT_CORE_FWD_HPP
- #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<>;
- }
- #endif
- // #include "type_info.hpp"
- #ifndef ENTT_CORE_TYPE_INFO_HPP
- #define ENTT_CORE_TYPE_INFO_HPP
- #include <string_view>
- #include <type_traits>
- // #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 "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;
- };
- }
- /**
- * 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 identifers 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.
- *
- * @tparam Char Character type.
- */
- template<typename Char>
- class basic_hashed_string {
- using traits_type = internal::fnv1a_traits<id_type>;
- struct const_wrapper {
- // non-explicit constructor on purpose
- constexpr const_wrapper(const Char *curr) ENTT_NOEXCEPT: str{curr} {}
- const Char *str;
- };
- // Fowler–Noll–Vo hash function v. 1a - the good
- [[nodiscard]] static constexpr id_type helper(const Char *curr) ENTT_NOEXCEPT {
- auto value = traits_type::offset;
- while(*curr != 0) {
- value = (value ^ static_cast<traits_type::type>(*(curr++))) * traits_type::prime;
- }
- return value;
- }
- public:
- /*! @brief Character type. */
- using value_type = Char;
- /*! @brief Unsigned integer type. */
- using hash_type = id_type;
- /**
- * @brief Returns directly the numeric representation of a string view.
- * @param str Human-readable identifer.
- * @param size Length of the string to hash.
- * @return The numeric representation of the string.
- */
- [[nodiscard]] static constexpr hash_type value(const value_type *str, std::size_t size) ENTT_NOEXCEPT {
- id_type partial{traits_type::offset};
- while(size--) { partial = (partial^(str++)[0])*traits_type::prime; }
- return partial;
- }
- /**
- * @brief Returns directly the numeric representation of a string.
- *
- * Forcing template resolution avoids implicit conversions. An
- * human-readable identifier can be anything but a plain, old bunch of
- * characters.<br/>
- * Example of use:
- * @code{.cpp}
- * const auto value = basic_hashed_string<char>::to_value("my.png");
- * @endcode
- *
- * @tparam N Number of characters of the identifier.
- * @param str Human-readable identifer.
- * @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 helper(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 hash_type value(const_wrapper wrapper) ENTT_NOEXCEPT {
- return helper(wrapper.str);
- }
- /*! @brief Constructs an empty hashed string. */
- constexpr basic_hashed_string() ENTT_NOEXCEPT
- : str{nullptr}, hash{}
- {}
- /**
- * @brief Constructs a hashed string from an array of const characters.
- *
- * Forcing template resolution avoids implicit conversions. An
- * human-readable identifier can be anything but a plain, old bunch of
- * characters.<br/>
- * Example of use:
- * @code{.cpp}
- * basic_hashed_string<char> hs{"my.png"};
- * @endcode
- *
- * @tparam N Number of characters of the identifier.
- * @param curr Human-readable identifer.
- */
- template<std::size_t N>
- constexpr basic_hashed_string(const value_type (&curr)[N]) ENTT_NOEXCEPT
- : str{curr}, hash{helper(curr)}
- {}
- /**
- * @brief Explicit constructor on purpose to avoid constructing a hashed
- * string directly from a `const value_type *`.
- * @param wrapper Helps achieving the purpose by relying on overloading.
- */
- explicit constexpr basic_hashed_string(const_wrapper wrapper) ENTT_NOEXCEPT
- : str{wrapper.str}, hash{helper(wrapper.str)}
- {}
- /**
- * @brief Returns the human-readable representation of a hashed string.
- * @return The string used to initialize the instance.
- */
- [[nodiscard]] constexpr const value_type * data() const ENTT_NOEXCEPT {
- return str;
- }
- /**
- * @brief Returns the numeric representation of a hashed string.
- * @return The numeric representation of the instance.
- */
- [[nodiscard]] constexpr hash_type value() const ENTT_NOEXCEPT {
- return 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 instance.
- */
- [[nodiscard]] constexpr operator hash_type() const ENTT_NOEXCEPT { return value(); }
- /**
- * @brief Compares two hashed strings.
- * @param other Hashed string with which to compare.
- * @return True if the two hashed strings are identical, false otherwise.
- */
- [[nodiscard]] constexpr bool operator==(const basic_hashed_string &other) const ENTT_NOEXCEPT {
- return hash == other.hash;
- }
- private:
- const value_type *str;
- hash_type hash;
- };
- /**
- * @brief Deduction guide.
- *
- * It allows to deduce the character type of the hashed string directly from a
- * human-readable identifer provided to the constructor.
- *
- * @tparam Char Character type.
- * @tparam N Number of characters of the identifier.
- * @param str Human-readable identifer.
- */
- 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 == 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 entt::hashed_string operator"" _hs(const char *str, std::size_t) ENTT_NOEXCEPT {
- return entt::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 entt::hashed_wstring operator"" _hws(const wchar_t *str, std::size_t) ENTT_NOEXCEPT {
- return entt::hashed_wstring{str};
- }
- }
- }
- #endif
- // #include "fwd.hpp"
- namespace entt {
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- namespace internal {
- struct ENTT_API type_seq 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;
- }
- }
- /**
- * 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_seq 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_seq::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_seq<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. */
- class type_info final {
- template<typename>
- friend type_info type_id() ENTT_NOEXCEPT;
- type_info(id_type seq_v, id_type hash_v, std::string_view name_v) ENTT_NOEXCEPT
- : seq_value{seq_v},
- hash_value{hash_v},
- name_value{name_v}
- {}
- public:
- /*! @brief Default constructor. */
- type_info() ENTT_NOEXCEPT
- : type_info({}, {}, {})
- {}
- /*! @brief Default copy constructor. */
- type_info(const type_info &) ENTT_NOEXCEPT = default;
- /*! @brief Default move constructor. */
- type_info(type_info &&) ENTT_NOEXCEPT = default;
- /**
- * @brief Default copy assignment operator.
- * @return This type info object.
- */
- type_info & operator=(const type_info &) ENTT_NOEXCEPT = default;
- /**
- * @brief Default move assignment operator.
- * @return This type info object.
- */
- type_info & operator=(type_info &&) ENTT_NOEXCEPT = default;
- /**
- * @brief Checks if a type info object is properly initialized.
- * @return True if the object is properly initialized, false otherwise.
- */
- [[nodiscard]] explicit operator bool() const ENTT_NOEXCEPT {
- return name_value.data() != nullptr;
- }
- /**
- * @brief Type sequential identifier.
- * @return Type sequential identifier.
- */
- [[nodiscard]] id_type seq() const ENTT_NOEXCEPT {
- return seq_value;
- }
- /**
- * @brief Type hash.
- * @return Type hash.
- */
- [[nodiscard]] id_type hash() const ENTT_NOEXCEPT {
- return hash_value;
- }
- /**
- * @brief Type name.
- * @return Type name.
- */
- [[nodiscard]] std::string_view name() const ENTT_NOEXCEPT {
- return name_value;
- }
- /**
- * @brief Compares the contents of two type info objects.
- * @param other Object with which to compare.
- * @return False if the two contents differ, true otherwise.
- */
- [[nodiscard]] bool operator==(const type_info &other) const ENTT_NOEXCEPT {
- return hash_value == other.hash_value;
- }
- private:
- id_type seq_value;
- id_type hash_value;
- std::string_view name_value;
- };
- /**
- * @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 contents differ, false otherwise.
- */
- [[nodiscard]] inline bool operator!=(const type_info &lhs, const type_info &rhs) ENTT_NOEXCEPT {
- return !(lhs == rhs);
- }
- /**
- * @brief Returns the type info object for a given type.
- * @tparam Type Type for which to generate a type info object.
- * @return The type info object for the given type.
- */
- template<typename Type>
- [[nodiscard]] type_info type_id() ENTT_NOEXCEPT {
- return type_info{
- type_seq<std::remove_cv_t<std::remove_reference_t<Type>>>::value(),
- type_hash<std::remove_cv_t<std::remove_reference_t<Type>>>::value(),
- type_name<std::remove_cv_t<std::remove_reference_t<Type>>>::value()
- };
- }
- }
- #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<class 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_t = 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_v = 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::disjunction_v<std::is_same<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<class 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;
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- namespace internal {
- template<typename>
- [[nodiscard]] constexpr bool is_equality_comparable(...) { return false; }
- template<typename Type>
- [[nodiscard]] constexpr auto is_equality_comparable(choice_t<0>)
- -> decltype(std::declval<Type>() == std::declval<Type>()) { return true; }
- template<typename Type>
- [[nodiscard]] constexpr auto is_equality_comparable(choice_t<1>)
- -> decltype(std::declval<typename Type::value_type>(), std::declval<Type>() == std::declval<Type>()) {
- if constexpr(std::is_same_v<typename Type::value_type, Type>) {
- return is_equality_comparable<Type>(choice<0>);
- } else {
- return is_equality_comparable<typename Type::value_type>(choice<2>);
- }
- }
- template<typename Type>
- [[nodiscard]] constexpr auto is_equality_comparable(choice_t<2>)
- -> decltype(std::declval<typename Type::mapped_type>(), std::declval<Type>() == std::declval<Type>()) {
- return is_equality_comparable<typename Type::key_type>(choice<2>) && is_equality_comparable<typename Type::mapped_type>(choice<2>);
- }
- }
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /**
- * @brief Provides the member constant `value` to true if a given type is
- * equality comparable, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_equality_comparable: std::bool_constant<internal::is_equality_comparable<Type>(choice<2>)> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<class Type>
- inline constexpr bool is_equality_comparable_v = is_equality_comparable<Type>::value;
- /*! @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 {};
- /*! @copydoc is_iterator */
- template<typename Type>
- struct is_iterator<Type, std::void_t<typename std::iterator_traits<Type>::iterator_category>>
- : std::true_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 of the
- * required iterator type, false otherwise.
- * @tparam Type The type to test.
- * @tparam It Required iterator type.
- */
- template<typename Type, typename It, typename = void>
- struct is_iterator_type: std::false_type {};
- /*! @copydoc is_iterator_type */
- template<typename Type, typename It>
- struct is_iterator_type<Type, It, std::enable_if_t<is_iterator_v<Type> && std::is_same_v<Type, It>>>
- : std::true_type
- {};
- /*! @copydoc is_iterator_type */
- template<typename Type, typename It>
- struct is_iterator_type<Type, It, std::enable_if_t<!std::is_same_v<Type, It>, std::void_t<typename It::iterator_type>>>
- : is_iterator_type<Type, typename It::iterator_type>
- {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- * @tparam It Required iterator type.
- */
- template<typename Type, typename It>
- inline constexpr bool is_iterator_type_v = is_iterator_type<Type, It>::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;
- }
- #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, DTOR, COMP, ADDR, CADDR, TYPE };
- 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 &, 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>
- [[nodiscard]] static constexpr policy type_to_policy() {
- if constexpr(std::is_lvalue_reference_v<Type>) {
- if constexpr(std::is_const_v<std::remove_reference_t<Type>>) {
- return policy::CREF;
- } else {
- return policy::REF;
- }
- } else {
- return policy::OWNER;
- }
- }
- template<typename Type>
- [[nodiscard]] static bool compare(const void *lhs, const void *rhs) {
- if constexpr(!std::is_function_v<Type> && is_equality_comparable_v<Type>) {
- return *static_cast<const Type *>(lhs) == *static_cast<const Type *>(rhs);
- } else {
- return lhs == rhs;
- }
- }
- template<typename Type>
- static const void * basic_vtable([[maybe_unused]] const operation op, [[maybe_unused]] const basic_any &from, [[maybe_unused]] void *to) {
- static_assert(std::is_same_v<std::remove_reference_t<std::remove_const_t<Type>>, Type>, "Invalid type");
- if constexpr(!std::is_void_v<Type>) {
- const Type *instance = (in_situ<Type> && from.mode == policy::OWNER)
- ? ENTT_LAUNDER(reinterpret_cast<const Type *>(&from.storage))
- : static_cast<const Type *>(from.instance);
- switch(op) {
- case operation::COPY:
- if constexpr(std::is_copy_constructible_v<Type>) {
- static_cast<basic_any *>(to)->emplace<Type>(*instance);
- }
- break;
- case operation::MOVE:
- if constexpr(in_situ<Type>) {
- if(from.mode == policy::OWNER) {
- return new (&static_cast<basic_any *>(to)->storage) Type{std::move(*const_cast<Type *>(instance))};
- }
- }
- return (static_cast<basic_any *>(to)->instance = std::exchange(const_cast<basic_any &>(from).instance, nullptr));
- case operation::DTOR:
- if(from.mode == policy::OWNER) {
- if constexpr(in_situ<Type>) {
- instance->~Type();
- } else if constexpr(std::is_array_v<Type>) {
- delete[] instance;
- } else {
- delete instance;
- }
- }
- break;
- case operation::COMP:
- return compare<Type>(instance, (*static_cast<const basic_any **>(to))->data()) ? to : nullptr;
- case operation::ADDR:
- if(from.mode == policy::CREF) {
- return nullptr;
- }
- [[fallthrough]];
- case operation::CADDR:
- return instance;
- case operation::TYPE:
- *static_cast<type_info *>(to) = type_id<Type>();
- break;
- }
- }
- return nullptr;
- }
- template<typename Type, typename... Args>
- void initialize([[maybe_unused]] Args &&... args) {
- if constexpr(!std::is_void_v<Type>) {
- if constexpr(std::is_lvalue_reference_v<Type>) {
- static_assert(sizeof...(Args) == 1u && (std::is_lvalue_reference_v<Args> && ...), "Invalid arguments");
- 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()},
- 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. */
- basic_any() ENTT_NOEXCEPT
- : instance{},
- vtable{&basic_vtable<void>},
- 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)
- : instance{},
- vtable{&basic_vtable<std::remove_const_t<std::remove_reference_t<Type>>>},
- mode{type_to_policy<Type>()}
- {
- initialize<Type>(std::forward<Args>(args)...);
- }
- /**
- * @brief Constructs a wrapper that holds an unmanaged object.
- * @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>
- basic_any(std::reference_wrapper<Type> value) ENTT_NOEXCEPT
- : basic_any{}
- {
- // invokes deprecated assignment operator (and avoids issues with vs2017)
- *this = value;
- }
- /**
- * @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)
- : instance{},
- vtable{&basic_vtable<std::decay_t<Type>>},
- mode{policy::OWNER}
- {
- 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)
- : instance{},
- vtable{&basic_vtable<void>},
- mode{policy::OWNER}
- {
- other.vtable(operation::COPY, other, this);
- }
- /**
- * @brief Move constructor.
- * @param other The instance to move from.
- */
- basic_any(basic_any &&other) ENTT_NOEXCEPT
- : instance{},
- vtable{other.vtable},
- mode{other.mode}
- {
- vtable(operation::MOVE, other, this);
- }
- /*! @brief Frees the internal storage, whatever it means. */
- ~basic_any() {
- vtable(operation::DTOR, *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();
- 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 {
- std::exchange(vtable, other.vtable)(operation::DTOR, *this, nullptr);
- other.vtable(operation::MOVE, other, this);
- 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>
- [[deprecated("Use std::in_place_type<T &>, entt::make_any<T &>, emplace<Type &> or forward_as_any instead")]]
- basic_any & operator=(std::reference_wrapper<Type> value) ENTT_NOEXCEPT {
- emplace<Type &>(value.get());
- 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 type of the contained object.
- * @return The type of the contained object, if any.
- */
- [[nodiscard]] type_info type() const ENTT_NOEXCEPT {
- type_info info{};
- vtable(operation::TYPE, *this, &info);
- 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(operation::CADDR, *this, nullptr);
- }
- /*! @copydoc data */
- [[nodiscard]] void * data() ENTT_NOEXCEPT {
- return const_cast<void *>(vtable(operation::ADDR, *this, 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) {
- std::exchange(vtable, &basic_vtable<std::remove_const_t<std::remove_reference_t<Type>>>)(operation::DTOR, *this, nullptr);
- mode = type_to_policy<Type>();
- initialize<Type>(std::forward<Args>(args)...);
- }
- /*! @brief Destroys contained object */
- void reset() {
- std::exchange(vtable, &basic_vtable<void>)(operation::DTOR, *this, 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(operation::CADDR, *this, nullptr) == 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 {
- const basic_any *trampoline = &other;
- return type() == other.type() && (vtable(operation::COMP, *this, &trampoline) || !other.data());
- }
- /**
- * @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; };
- 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 {
- // 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>(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 {
- return (data->type() == type_id<Type>() ? static_cast<const Type *>(data->data()) : nullptr);
- }
- /*! @copydoc any_cast */
- template<typename Type, std::size_t Len, std::size_t Align>
- Type * any_cast(basic_any<Len, Align> *data) ENTT_NOEXCEPT {
- // last attempt to make wrappers for const references return their values
- return (data->type() == type_id<Type>() ? static_cast<Type *>(static_cast<constness_as_t<basic_any<Len, Align>, Type> *>(data)->data()) : nullptr);
- }
- /**
- * @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)};
- }
- }
- #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 "../config/config.h"
- // #include "../core/attribute.h"
- // #include "hashed_string.hpp"
- // #include "fwd.hpp"
- namespace entt {
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- namespace internal {
- struct ENTT_API type_seq 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;
- }
- }
- /**
- * 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_seq 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_seq::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_seq<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. */
- class type_info final {
- template<typename>
- friend type_info type_id() ENTT_NOEXCEPT;
- type_info(id_type seq_v, id_type hash_v, std::string_view name_v) ENTT_NOEXCEPT
- : seq_value{seq_v},
- hash_value{hash_v},
- name_value{name_v}
- {}
- public:
- /*! @brief Default constructor. */
- type_info() ENTT_NOEXCEPT
- : type_info({}, {}, {})
- {}
- /*! @brief Default copy constructor. */
- type_info(const type_info &) ENTT_NOEXCEPT = default;
- /*! @brief Default move constructor. */
- type_info(type_info &&) ENTT_NOEXCEPT = default;
- /**
- * @brief Default copy assignment operator.
- * @return This type info object.
- */
- type_info & operator=(const type_info &) ENTT_NOEXCEPT = default;
- /**
- * @brief Default move assignment operator.
- * @return This type info object.
- */
- type_info & operator=(type_info &&) ENTT_NOEXCEPT = default;
- /**
- * @brief Checks if a type info object is properly initialized.
- * @return True if the object is properly initialized, false otherwise.
- */
- [[nodiscard]] explicit operator bool() const ENTT_NOEXCEPT {
- return name_value.data() != nullptr;
- }
- /**
- * @brief Type sequential identifier.
- * @return Type sequential identifier.
- */
- [[nodiscard]] id_type seq() const ENTT_NOEXCEPT {
- return seq_value;
- }
- /**
- * @brief Type hash.
- * @return Type hash.
- */
- [[nodiscard]] id_type hash() const ENTT_NOEXCEPT {
- return hash_value;
- }
- /**
- * @brief Type name.
- * @return Type name.
- */
- [[nodiscard]] std::string_view name() const ENTT_NOEXCEPT {
- return name_value;
- }
- /**
- * @brief Compares the contents of two type info objects.
- * @param other Object with which to compare.
- * @return False if the two contents differ, true otherwise.
- */
- [[nodiscard]] bool operator==(const type_info &other) const ENTT_NOEXCEPT {
- return hash_value == other.hash_value;
- }
- private:
- id_type seq_value;
- id_type hash_value;
- std::string_view name_value;
- };
- /**
- * @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 contents differ, false otherwise.
- */
- [[nodiscard]] inline bool operator!=(const type_info &lhs, const type_info &rhs) ENTT_NOEXCEPT {
- return !(lhs == rhs);
- }
- /**
- * @brief Returns the type info object for a given type.
- * @tparam Type Type for which to generate a type info object.
- * @return The type info object for the given type.
- */
- template<typename Type>
- [[nodiscard]] type_info type_id() ENTT_NOEXCEPT {
- return type_info{
- type_seq<std::remove_cv_t<std::remove_reference_t<Type>>>::value(),
- type_hash<std::remove_cv_t<std::remove_reference_t<Type>>>::value(),
- type_name<std::remove_cv_t<std::remove_reference_t<Type>>>::value()
- };
- }
- }
- #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<class 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_t = 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_v = 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::disjunction_v<std::is_same<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<class 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;
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- namespace internal {
- template<typename>
- [[nodiscard]] constexpr bool is_equality_comparable(...) { return false; }
- template<typename Type>
- [[nodiscard]] constexpr auto is_equality_comparable(choice_t<0>)
- -> decltype(std::declval<Type>() == std::declval<Type>()) { return true; }
- template<typename Type>
- [[nodiscard]] constexpr auto is_equality_comparable(choice_t<1>)
- -> decltype(std::declval<typename Type::value_type>(), std::declval<Type>() == std::declval<Type>()) {
- if constexpr(std::is_same_v<typename Type::value_type, Type>) {
- return is_equality_comparable<Type>(choice<0>);
- } else {
- return is_equality_comparable<typename Type::value_type>(choice<2>);
- }
- }
- template<typename Type>
- [[nodiscard]] constexpr auto is_equality_comparable(choice_t<2>)
- -> decltype(std::declval<typename Type::mapped_type>(), std::declval<Type>() == std::declval<Type>()) {
- return is_equality_comparable<typename Type::key_type>(choice<2>) && is_equality_comparable<typename Type::mapped_type>(choice<2>);
- }
- }
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /**
- * @brief Provides the member constant `value` to true if a given type is
- * equality comparable, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_equality_comparable: std::bool_constant<internal::is_equality_comparable<Type>(choice<2>)> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<class Type>
- inline constexpr bool is_equality_comparable_v = is_equality_comparable<Type>::value;
- /*! @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 {};
- /*! @copydoc is_iterator */
- template<typename Type>
- struct is_iterator<Type, std::void_t<typename std::iterator_traits<Type>::iterator_category>>
- : std::true_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 of the
- * required iterator type, false otherwise.
- * @tparam Type The type to test.
- * @tparam It Required iterator type.
- */
- template<typename Type, typename It, typename = void>
- struct is_iterator_type: std::false_type {};
- /*! @copydoc is_iterator_type */
- template<typename Type, typename It>
- struct is_iterator_type<Type, It, std::enable_if_t<is_iterator_v<Type> && std::is_same_v<Type, It>>>
- : std::true_type
- {};
- /*! @copydoc is_iterator_type */
- template<typename Type, typename It>
- struct is_iterator_type<Type, It, std::enable_if_t<!std::is_same_v<Type, It>, std::void_t<typename It::iterator_type>>>
- : is_iterator_type<Type, typename It::iterator_type>
- {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- * @tparam It Required iterator type.
- */
- template<typename Type, typename It>
- inline constexpr bool is_iterator_type_v = is_iterator_type<Type, It>::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;
- }
- #endif
- // #include "fwd.hpp"
- #ifndef ENTT_POLY_FWD_HPP
- #define ENTT_POLY_FWD_HPP
- #include <type_traits>
- namespace entt {
- template<typename, std::size_t Len, 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, sizeof(double[2])>;
- }
- #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<auto Member, typename... Args>
- poly_inspector invoke(Args &&... args) const;
- /*! @copydoc invoke */
- template<auto 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...>)
- -> decltype(std::make_tuple(vtable_entry(Candidate)...));
- template<typename... Func>
- [[nodiscard]] static constexpr auto make_vtable(type_list<Func...>) {
- if constexpr(sizeof...(Func) == 0) {
- 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...)) {
- 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...>) {
- type impl{};
- (fill_vtable_entry<Type, value_list_element_v<Index, typename Concept::template impl<Type>>>(std::get<Index>(impl)), ...);
- return impl;
- }
- public:
- /*! @brief Virtual table type. */
- using type = decltype(make_vtable(Concept{}));
- /**
- * @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 const auto * instance() {
- static_assert(std::is_same_v<Type, std::decay_t<Type>>, "Type differs from its decayed form");
- static const auto vtable = fill_vtable<Type>(std::make_index_sequence<Concept::template impl<Type>::size>{});
- 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<auto Member, typename... Args>
- [[nodiscard]] decltype(auto) invoke(const poly_base &self, Args &&... args) const {
- const auto &poly = static_cast<const Poly &>(self);
- return std::get<Member>(*poly.vtable)(poly.storage, std::forward<Args>(args)...);
- }
- /*! @copydoc invoke */
- template<auto Member, typename... Args>
- [[nodiscard]] decltype(auto) invoke(poly_base &self, Args &&... args) {
- auto &poly = static_cast<Poly &>(self);
- 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<auto 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>;
- using vtable_type = typename poly_vtable<Concept, Len, Align>::type;
- public:
- /*! @brief Concept type. */
- using concept_type = typename Concept::template type<poly_base<basic_poly>>;
- /*! @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_const_t<std::remove_reference_t<Type>>>()}
- {}
- /**
- * @brief Constructs a poly from a given value.
- * @tparam Type Type of object to use to initialize the poly.
- * @param value An instance of an object to use to initialize the poly.
- */
- template<typename Type, typename = std::enable_if_t<!std::is_same_v<std::remove_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 Copy constructor.
- * @param other The instance to copy from.
- */
- basic_poly(const basic_poly &other) = default;
- /**
- * @brief Move constructor.
- * @param other The instance to move from.
- */
- basic_poly(basic_poly &&other) ENTT_NOEXCEPT
- : basic_poly{}
- {
- swap(*this, other);
- }
- /**
- * @brief Assignment operator.
- * @param other The instance to assign from.
- * @return This poly object.
- */
- basic_poly & operator=(basic_poly other) {
- swap(other, *this);
- return *this;
- }
- /**
- * @brief Returns the type of the contained object.
- * @return The type of the contained object, if any.
- */
- [[nodiscard]] 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) {
- *this = basic_poly{std::in_place_type<Type>, std::forward<Args>(args)...};
- }
- /*! @brief Destroys contained object */
- void reset() {
- *this = basic_poly{};
- }
- /**
- * @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 !(vtable == nullptr);
- }
- /**
- * @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 Swaps two poly objects.
- * @param lhs A valid poly object.
- * @param rhs A valid poly object.
- */
- friend void swap(basic_poly &lhs, basic_poly &rhs) {
- using std::swap;
- swap(lhs.storage, rhs.storage);
- swap(lhs.vtable, rhs.vtable);
- }
- /**
- * @brief Aliasing constructor.
- * @return A poly that shares a reference to an unmanaged object.
- */
- [[nodiscard]] basic_poly as_ref() ENTT_NOEXCEPT {
- basic_poly ref = std::as_const(*this).as_ref();
- ref.storage = storage.as_ref();
- 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;
- const vtable_type *vtable;
- };
- }
- #endif
- // #include "process/process.hpp"
- #ifndef ENTT_PROCESS_PROCESS_HPP
- #define ENTT_PROCESS_PROCESS_HPP
- #include <utility>
- #include <type_traits>
- // #include "../config/config.h"
- #ifndef ENTT_CONFIG_CONFIG_H
- #define ENTT_CONFIG_CONFIG_H
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_NOEXCEPT noexcept
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_NOEXCEPT
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606L
- # include <new>
- # define ENTT_LAUNDER(expr) std::launder(expr)
- #else
- # define ENTT_LAUNDER(expr) expr
- #endif
- #ifndef ENTT_USE_ATOMIC
- # define ENTT_MAYBE_ATOMIC(Type) Type
- #else
- # include <atomic>
- # define ENTT_MAYBE_ATOMIC(Type) std::atomic<Type>
- #endif
- #ifndef ENTT_ID_TYPE
- # include <cstdint>
- # define ENTT_ID_TYPE std::uint32_t
- #endif
- #ifdef ENTT_SPARSE_PAGE
- static_assert(ENTT_SPARSE_PAGE && ((ENTT_SPARSE_PAGE & (ENTT_SPARSE_PAGE - 1)) == 0), "ENTT_SPARSE_PAGE must be a power of two");
- #else
- # define ENTT_SPARSE_PAGE 4096
- #endif
- #ifdef ENTT_PACKED_PAGE
- static_assert(ENTT_PACKED_PAGE && ((ENTT_PACKED_PAGE & (ENTT_PACKED_PAGE - 1)) == 0), "ENTT_PACKED_PAGE must be a power of two");
- #else
- # 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
- # include <type_traits>
- # define ENTT_IGNORE_IF_EMPTY std::false_type
- #else
- # include <type_traits>
- # define ENTT_IGNORE_IF_EMPTY std::true_type
- #endif
- #ifndef ENTT_STANDARD_CPP
- # 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
- #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: unsigned int {
- 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() {
- 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(); });
- }
- };
- }
- #endif
- // #include "process/scheduler.hpp"
- #ifndef ENTT_PROCESS_SCHEDULER_HPP
- #define ENTT_PROCESS_SCHEDULER_HPP
- #include <vector>
- #include <memory>
- #include <utility>
- #include <algorithm>
- #include <type_traits>
- // #include "../config/config.h"
- // #include "process.hpp"
- #ifndef ENTT_PROCESS_PROCESS_HPP
- #define ENTT_PROCESS_PROCESS_HPP
- #include <utility>
- #include <type_traits>
- // #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: unsigned int {
- 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() {
- 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(); });
- }
- };
- }
- #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(process_handler &, Delta, void *);
- using abort_fn_type = void(process_handler &, 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)
- : 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(process_handler &handler, const Delta delta, void *data) {
- auto *process = static_cast<Proc *>(handler.instance.get());
- process->tick(delta, data);
- if(process->rejected()) {
- return true;
- } else if(process->finished()) {
- if(handler.next) {
- handler = std::move(*handler.next);
- // forces the process to exit the uninitialized state
- return handler.update(handler, {}, nullptr);
- }
- return true;
- }
- return false;
- }
- template<typename Proc>
- static void abort(process_handler &handler, const bool immediately) {
- static_cast<Proc *>(handler.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>};
- process_handler handler{std::move(proc), &scheduler::update<Proc>, &scheduler::abort<Proc>, nullptr};
- // forces the process to exit the uninitialized state
- handler.update(handler, {}, nullptr);
- return continuation{&handlers.emplace_back(std::move(handler))};
- }
- /**
- * @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) {
- auto sz = handlers.size();
- for(auto pos = handlers.size(); pos; --pos) {
- auto &handler = handlers[pos-1];
- if(const auto dead = handler.update(handler, delta, data); dead) {
- std::swap(handler, handlers[--sz]);
- }
- }
- handlers.erase(handlers.begin() + sz, handlers.end());
- }
- /**
- * @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) {
- decltype(handlers) exec;
- exec.swap(handlers);
- for(auto &&handler: exec) {
- handler.abort(handler, immediately);
- }
- std::move(handlers.begin(), handlers.end(), std::back_inserter(exec));
- handlers.swap(exec);
- }
- private:
- std::vector<process_handler> handlers{};
- };
- }
- #endif
- // #include "resource/cache.hpp"
- #ifndef ENTT_RESOURCE_CACHE_HPP
- #define ENTT_RESOURCE_CACHE_HPP
- #include <type_traits>
- #include <unordered_map>
- #include <utility>
- // #include "../config/config.h"
- #ifndef ENTT_CONFIG_CONFIG_H
- #define ENTT_CONFIG_CONFIG_H
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_NOEXCEPT noexcept
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_NOEXCEPT
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606L
- # include <new>
- # define ENTT_LAUNDER(expr) std::launder(expr)
- #else
- # define ENTT_LAUNDER(expr) expr
- #endif
- #ifndef ENTT_USE_ATOMIC
- # define ENTT_MAYBE_ATOMIC(Type) Type
- #else
- # include <atomic>
- # define ENTT_MAYBE_ATOMIC(Type) std::atomic<Type>
- #endif
- #ifndef ENTT_ID_TYPE
- # include <cstdint>
- # define ENTT_ID_TYPE std::uint32_t
- #endif
- #ifdef ENTT_SPARSE_PAGE
- static_assert(ENTT_SPARSE_PAGE && ((ENTT_SPARSE_PAGE & (ENTT_SPARSE_PAGE - 1)) == 0), "ENTT_SPARSE_PAGE must be a power of two");
- #else
- # define ENTT_SPARSE_PAGE 4096
- #endif
- #ifdef ENTT_PACKED_PAGE
- static_assert(ENTT_PACKED_PAGE && ((ENTT_PACKED_PAGE & (ENTT_PACKED_PAGE - 1)) == 0), "ENTT_PACKED_PAGE must be a power of two");
- #else
- # 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
- # include <type_traits>
- # define ENTT_IGNORE_IF_EMPTY std::false_type
- #else
- # include <type_traits>
- # define ENTT_IGNORE_IF_EMPTY std::true_type
- #endif
- #ifndef ENTT_STANDARD_CPP
- # 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
- #endif
- // #include "../core/fwd.hpp"
- #ifndef ENTT_CORE_FWD_HPP
- #define ENTT_CORE_FWD_HPP
- #include <type_traits>
- // #include "../config/config.h"
- #ifndef ENTT_CONFIG_CONFIG_H
- #define ENTT_CONFIG_CONFIG_H
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_NOEXCEPT noexcept
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_NOEXCEPT
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606L
- # include <new>
- # define ENTT_LAUNDER(expr) std::launder(expr)
- #else
- # define ENTT_LAUNDER(expr) expr
- #endif
- #ifndef ENTT_USE_ATOMIC
- # define ENTT_MAYBE_ATOMIC(Type) Type
- #else
- # include <atomic>
- # define ENTT_MAYBE_ATOMIC(Type) std::atomic<Type>
- #endif
- #ifndef ENTT_ID_TYPE
- # include <cstdint>
- # define ENTT_ID_TYPE std::uint32_t
- #endif
- #ifdef ENTT_SPARSE_PAGE
- static_assert(ENTT_SPARSE_PAGE && ((ENTT_SPARSE_PAGE & (ENTT_SPARSE_PAGE - 1)) == 0), "ENTT_SPARSE_PAGE must be a power of two");
- #else
- # define ENTT_SPARSE_PAGE 4096
- #endif
- #ifdef ENTT_PACKED_PAGE
- static_assert(ENTT_PACKED_PAGE && ((ENTT_PACKED_PAGE & (ENTT_PACKED_PAGE - 1)) == 0), "ENTT_PACKED_PAGE must be a power of two");
- #else
- # 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
- # include <type_traits>
- # define ENTT_IGNORE_IF_EMPTY std::false_type
- #else
- # include <type_traits>
- # define ENTT_IGNORE_IF_EMPTY std::true_type
- #endif
- #ifndef ENTT_STANDARD_CPP
- # 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
- #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<>;
- }
- #endif
- // #include "handle.hpp"
- #ifndef ENTT_RESOURCE_HANDLE_HPP
- #define ENTT_RESOURCE_HANDLE_HPP
- #include <memory>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- // #include "fwd.hpp"
- #ifndef ENTT_RESOURCE_FWD_HPP
- #define ENTT_RESOURCE_FWD_HPP
- namespace entt {
- template<typename>
- struct resource_cache;
- template<typename>
- class resource_handle;
- template<typename, typename>
- class resource_loader;
- }
- #endif
- namespace entt {
- /**
- * @brief Shared resource handle.
- *
- * A shared resource handle is a small class that wraps a resource and keeps it
- * alive even if it's deleted from the cache. It can be either copied or
- * moved. A handle shares a reference to the same resource with all the other
- * handles constructed for the same identifier.<br/>
- * As a rule of thumb, resources should never be copied nor moved. Handles are
- * the way to go to keep references to them.
- *
- * @tparam Resource Type of resource managed by a handle.
- */
- template<typename Resource>
- class resource_handle {
- /*! @brief Resource handles are friends with each other. */
- template<typename>
- friend class resource_handle;
- public:
- /*! @brief Default constructor. */
- resource_handle() ENTT_NOEXCEPT = default;
- /**
- * @brief Creates a handle from a shared pointer, namely a resource.
- * @param res A pointer to a properly initialized resource.
- */
- resource_handle(std::shared_ptr<Resource> res) ENTT_NOEXCEPT
- : resource{std::move(res)}
- {}
- /**
- * @brief Copy constructor.
- * @param other The instance to copy from.
- */
- resource_handle(const resource_handle<Resource> &other) ENTT_NOEXCEPT = default;
- /**
- * @brief Move constructor.
- * @param other The instance to move from.
- */
- resource_handle(resource_handle<Resource> &&other) ENTT_NOEXCEPT = default;
- /**
- * @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<!std::is_same_v<Other, Resource> && std::is_base_of_v<Resource, Other>>>
- resource_handle(const resource_handle<Other> &other) ENTT_NOEXCEPT
- : resource{other.resource}
- {}
- /**
- * @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<!std::is_same_v<Other, Resource> && std::is_base_of_v<Resource, Other>>>
- resource_handle(resource_handle<Other> &&other) ENTT_NOEXCEPT
- : resource{std::move(other.resource)}
- {}
- /**
- * @brief Copy assignment operator.
- * @param other The instance to copy from.
- * @return This resource handle.
- */
- resource_handle & operator=(const resource_handle<Resource> &other) ENTT_NOEXCEPT = default;
- /**
- * @brief Move assignment operator.
- * @param other The instance to move from.
- * @return This resource handle.
- */
- resource_handle & operator=(resource_handle<Resource> &&other) 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<!std::is_same_v<Other, Resource> && std::is_base_of_v<Resource, Other>, resource_handle &>
- operator=(const resource_handle<Other> &other) ENTT_NOEXCEPT {
- resource = other.resource;
- 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<!std::is_same_v<Other, Resource> && std::is_base_of_v<Resource, Other>, resource_handle &>
- operator=(resource_handle<Other> &&other) ENTT_NOEXCEPT {
- resource = std::move(other.resource);
- return *this;
- }
- /**
- * @brief Gets 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]] const Resource & get() const ENTT_NOEXCEPT {
- ENTT_ASSERT(static_cast<bool>(resource), "Invalid resource");
- return *resource;
- }
- /*! @copydoc get */
- [[nodiscard]] Resource & get() ENTT_NOEXCEPT {
- return const_cast<Resource &>(std::as_const(*this).get());
- }
- /*! @copydoc get */
- [[nodiscard]] operator const Resource & () const ENTT_NOEXCEPT {
- return get();
- }
- /*! @copydoc get */
- [[nodiscard]] operator Resource & () ENTT_NOEXCEPT {
- return get();
- }
- /*! @copydoc get */
- [[nodiscard]] const Resource & operator *() const ENTT_NOEXCEPT {
- return get();
- }
- /*! @copydoc get */
- [[nodiscard]] Resource & operator *() ENTT_NOEXCEPT {
- return get();
- }
- /**
- * @brief Gets a pointer to the managed resource.
- *
- * @warning
- * The behavior is undefined if the handle doesn't contain a resource.
- *
- * @return A pointer to the managed resource or `nullptr` if the handle
- * contains no resource at all.
- */
- [[nodiscard]] const Resource * operator->() const ENTT_NOEXCEPT {
- return resource.get();
- }
- /*! @copydoc operator-> */
- [[nodiscard]] Resource * operator->() ENTT_NOEXCEPT {
- return const_cast<Resource *>(std::as_const(*this).operator->());
- }
- /**
- * @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>(resource);
- }
- private:
- std::shared_ptr<Resource> resource;
- };
- }
- #endif
- // #include "loader.hpp"
- #ifndef ENTT_RESOURCE_LOADER_HPP
- #define ENTT_RESOURCE_LOADER_HPP
- // #include "fwd.hpp"
- // #include "handle.hpp"
- namespace entt {
- /**
- * @brief Base class for resource loaders.
- *
- * Resource loaders must inherit from this class and stay true to the CRTP
- * idiom. Moreover, a resource loader must expose a public, const member
- * function named `load` that accepts a variable number of arguments and returns
- * a handle to the resource just created.<br/>
- * As an example:
- *
- * @code{.cpp}
- * struct my_resource {};
- *
- * struct my_loader: entt::resource_loader<my_loader, my_resource> {
- * resource_handle<my_resource> load(int value) const {
- * // use the integer value somehow
- * return std::make_shared<my_resource>();
- * }
- * };
- * @endcode
- *
- * In general, resource loaders should not have a state or retain data of any
- * type. They should let the cache manage their resources instead.
- *
- * @note
- * Base class and CRTP idiom aren't strictly required with the current
- * implementation. One could argue that a cache can easily work with loaders of
- * any type. However, future changes won't be breaking ones by forcing the use
- * of a base class today and that's why the model is already in its place.
- *
- * @tparam Loader Type of the derived class.
- * @tparam Resource Type of resource for which to use the loader.
- */
- template<typename Loader, typename Resource>
- class resource_loader {
- /*! @brief Resource loaders are friends of their caches. */
- template<typename Other>
- friend struct resource_cache;
- /**
- * @brief Loads the resource and returns it.
- * @tparam Args Types of arguments for the loader.
- * @param args Arguments for the loader.
- * @return The resource just loaded or an empty pointer in case of errors.
- */
- template<typename... Args>
- [[nodiscard]] resource_handle<Resource> get(Args &&... args) const {
- return static_cast<const Loader *>(this)->load(std::forward<Args>(args)...);
- }
- };
- }
- #endif
- // #include "fwd.hpp"
- namespace entt {
- /**
- * @brief Simple cache for resources of a given type.
- *
- * Minimal implementation of a cache for resources of a given type. It doesn't
- * offer much functionalities but it's suitable for small or medium sized
- * applications and can be freely inherited to add targeted functionalities for
- * large sized applications.
- *
- * @tparam Resource Type of resources managed by a cache.
- */
- template<typename Resource>
- struct resource_cache {
- /*! @brief Unsigned integer type. */
- using size_type = std::size_t;
- /*! @brief Type of resources managed by a cache. */
- using resource_type = Resource;
- /*! @brief Default constructor. */
- resource_cache() = default;
- /*! @brief Default move constructor. */
- resource_cache(resource_cache &&) = default;
- /*! @brief Default move assignment operator. @return This cache. */
- resource_cache & operator=(resource_cache &&) = default;
- /**
- * @brief Number of resources managed by a cache.
- * @return Number of resources currently stored.
- */
- [[nodiscard]] size_type size() const ENTT_NOEXCEPT {
- return resources.size();
- }
- /**
- * @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 resources.empty();
- }
- /**
- * @brief Clears a cache and discards all its resources.
- *
- * Handles are not invalidated and the memory used by a resource isn't
- * freed as long as at least a handle keeps the resource itself alive.
- */
- void clear() ENTT_NOEXCEPT {
- resources.clear();
- }
- /**
- * @brief Loads the resource that corresponds to a given identifier.
- *
- * In case an identifier isn't already present in the cache, it loads its
- * resource and stores it aside for future uses. Arguments are forwarded
- * directly to the loader in order to construct properly the requested
- * resource.
- *
- * @note
- * If the identifier is already present in the cache, this function does
- * nothing and the arguments are simply discarded.
- *
- * @warning
- * If the resource cannot be loaded correctly, the returned handle will be
- * invalid and any use of it will result in undefined behavior.
- *
- * @tparam Loader Type of loader to use to load the resource if required.
- * @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 handle for the given resource.
- */
- template<typename Loader, typename... Args>
- resource_handle<Resource> load(const id_type id, Args &&... args) {
- if(auto it = resources.find(id); it == resources.cend()) {
- if(auto handle = temp<Loader>(std::forward<Args>(args)...); handle) {
- return (resources[id] = std::move(handle));
- }
- } else {
- return it->second;
- }
- return {};
- }
- /**
- * @brief Reloads a resource or loads it for the first time if not present.
- *
- * Equivalent to the following snippet (pseudocode):
- *
- * @code{.cpp}
- * cache.discard(id);
- * cache.load(id, args...);
- * @endcode
- *
- * Arguments are forwarded directly to the loader in order to construct
- * properly the requested resource.
- *
- * @warning
- * If the resource cannot be loaded correctly, the returned handle will be
- * invalid and any use of it will result in undefined behavior.
- *
- * @tparam Loader Type of loader to use to load the resource.
- * @tparam Args Types of arguments to use to load the resource.
- * @param id Unique resource identifier.
- * @param args Arguments to use to load the resource.
- * @return A handle for the given resource.
- */
- template<typename Loader, typename... Args>
- resource_handle<Resource> reload(const id_type id, Args &&... args) {
- return (discard(id), load<Loader>(id, std::forward<Args>(args)...));
- }
- /**
- * @brief Creates a temporary handle for a resource.
- *
- * Arguments are forwarded directly to the loader in order to construct
- * properly the requested resource. The handle isn't stored aside and the
- * cache isn't in charge of the lifetime of the resource itself.
- *
- * @tparam Loader Type of loader to use to load the resource.
- * @tparam Args Types of arguments to use to load the resource.
- * @param args Arguments to use to load the resource.
- * @return A handle for the given resource.
- */
- template<typename Loader, typename... Args>
- [[nodiscard]] resource_handle<Resource> temp(Args &&... args) const {
- return Loader{}.get(std::forward<Args>(args)...);
- }
- /**
- * @brief Creates a handle for a given resource identifier.
- *
- * A resource handle can be in a either valid or invalid state. In other
- * terms, a resource handle is properly initialized with a resource if the
- * cache contains the resource itself. Otherwise the returned handle is
- * uninitialized and accessing it results in undefined behavior.
- *
- * @sa resource_handle
- *
- * @param id Unique resource identifier.
- * @return A handle for the given resource.
- */
- [[nodiscard]] resource_handle<Resource> handle(const id_type id) const {
- if(auto it = resources.find(id); it != resources.cend()) {
- return 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 (resources.find(id) != resources.cend());
- }
- /**
- * @brief Discards the resource that corresponds to a given identifier.
- *
- * Handles are not invalidated and the memory used by the resource isn't
- * freed as long as at least a handle keeps the resource itself alive.
- *
- * @param id Unique resource identifier.
- */
- void discard(const id_type id) {
- if(auto it = resources.find(id); it != resources.end()) {
- resources.erase(it);
- }
- }
- /**
- * @brief Iterates all resources.
- *
- * The function object is invoked for each element. It is provided with
- * either the resource identifier, the resource handle or both of them.<br/>
- * The signature of the function must be equivalent to one of the following
- * forms:
- *
- * @code{.cpp}
- * void(const entt::id_type);
- * void(entt::resource_handle<Resource>);
- * void(const entt::id_type, entt::resource_handle<Resource>);
- * @endcode
- *
- * @tparam Func Type of the function object to invoke.
- * @param func A valid function object.
- */
- template <typename Func>
- void each(Func func) const {
- auto begin = resources.begin();
- auto end = resources.end();
- while(begin != end) {
- auto curr = begin++;
- if constexpr(std::is_invocable_v<Func, id_type>) {
- func(curr->first);
- } else if constexpr(std::is_invocable_v<Func, resource_handle<Resource>>) {
- func(curr->second);
- } else {
- func(curr->first, curr->second);
- }
- }
- }
- private:
- std::unordered_map<id_type, resource_handle<Resource>> resources;
- };
- }
- #endif
- // #include "resource/handle.hpp"
- #ifndef ENTT_RESOURCE_HANDLE_HPP
- #define ENTT_RESOURCE_HANDLE_HPP
- #include <memory>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- // #include "fwd.hpp"
- namespace entt {
- /**
- * @brief Shared resource handle.
- *
- * A shared resource handle is a small class that wraps a resource and keeps it
- * alive even if it's deleted from the cache. It can be either copied or
- * moved. A handle shares a reference to the same resource with all the other
- * handles constructed for the same identifier.<br/>
- * As a rule of thumb, resources should never be copied nor moved. Handles are
- * the way to go to keep references to them.
- *
- * @tparam Resource Type of resource managed by a handle.
- */
- template<typename Resource>
- class resource_handle {
- /*! @brief Resource handles are friends with each other. */
- template<typename>
- friend class resource_handle;
- public:
- /*! @brief Default constructor. */
- resource_handle() ENTT_NOEXCEPT = default;
- /**
- * @brief Creates a handle from a shared pointer, namely a resource.
- * @param res A pointer to a properly initialized resource.
- */
- resource_handle(std::shared_ptr<Resource> res) ENTT_NOEXCEPT
- : resource{std::move(res)}
- {}
- /**
- * @brief Copy constructor.
- * @param other The instance to copy from.
- */
- resource_handle(const resource_handle<Resource> &other) ENTT_NOEXCEPT = default;
- /**
- * @brief Move constructor.
- * @param other The instance to move from.
- */
- resource_handle(resource_handle<Resource> &&other) ENTT_NOEXCEPT = default;
- /**
- * @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<!std::is_same_v<Other, Resource> && std::is_base_of_v<Resource, Other>>>
- resource_handle(const resource_handle<Other> &other) ENTT_NOEXCEPT
- : resource{other.resource}
- {}
- /**
- * @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<!std::is_same_v<Other, Resource> && std::is_base_of_v<Resource, Other>>>
- resource_handle(resource_handle<Other> &&other) ENTT_NOEXCEPT
- : resource{std::move(other.resource)}
- {}
- /**
- * @brief Copy assignment operator.
- * @param other The instance to copy from.
- * @return This resource handle.
- */
- resource_handle & operator=(const resource_handle<Resource> &other) ENTT_NOEXCEPT = default;
- /**
- * @brief Move assignment operator.
- * @param other The instance to move from.
- * @return This resource handle.
- */
- resource_handle & operator=(resource_handle<Resource> &&other) 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<!std::is_same_v<Other, Resource> && std::is_base_of_v<Resource, Other>, resource_handle &>
- operator=(const resource_handle<Other> &other) ENTT_NOEXCEPT {
- resource = other.resource;
- 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<!std::is_same_v<Other, Resource> && std::is_base_of_v<Resource, Other>, resource_handle &>
- operator=(resource_handle<Other> &&other) ENTT_NOEXCEPT {
- resource = std::move(other.resource);
- return *this;
- }
- /**
- * @brief Gets 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]] const Resource & get() const ENTT_NOEXCEPT {
- ENTT_ASSERT(static_cast<bool>(resource), "Invalid resource");
- return *resource;
- }
- /*! @copydoc get */
- [[nodiscard]] Resource & get() ENTT_NOEXCEPT {
- return const_cast<Resource &>(std::as_const(*this).get());
- }
- /*! @copydoc get */
- [[nodiscard]] operator const Resource & () const ENTT_NOEXCEPT {
- return get();
- }
- /*! @copydoc get */
- [[nodiscard]] operator Resource & () ENTT_NOEXCEPT {
- return get();
- }
- /*! @copydoc get */
- [[nodiscard]] const Resource & operator *() const ENTT_NOEXCEPT {
- return get();
- }
- /*! @copydoc get */
- [[nodiscard]] Resource & operator *() ENTT_NOEXCEPT {
- return get();
- }
- /**
- * @brief Gets a pointer to the managed resource.
- *
- * @warning
- * The behavior is undefined if the handle doesn't contain a resource.
- *
- * @return A pointer to the managed resource or `nullptr` if the handle
- * contains no resource at all.
- */
- [[nodiscard]] const Resource * operator->() const ENTT_NOEXCEPT {
- return resource.get();
- }
- /*! @copydoc operator-> */
- [[nodiscard]] Resource * operator->() ENTT_NOEXCEPT {
- return const_cast<Resource *>(std::as_const(*this).operator->());
- }
- /**
- * @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>(resource);
- }
- private:
- std::shared_ptr<Resource> resource;
- };
- }
- #endif
- // #include "resource/loader.hpp"
- #ifndef ENTT_RESOURCE_LOADER_HPP
- #define ENTT_RESOURCE_LOADER_HPP
- // #include "fwd.hpp"
- // #include "handle.hpp"
- namespace entt {
- /**
- * @brief Base class for resource loaders.
- *
- * Resource loaders must inherit from this class and stay true to the CRTP
- * idiom. Moreover, a resource loader must expose a public, const member
- * function named `load` that accepts a variable number of arguments and returns
- * a handle to the resource just created.<br/>
- * As an example:
- *
- * @code{.cpp}
- * struct my_resource {};
- *
- * struct my_loader: entt::resource_loader<my_loader, my_resource> {
- * resource_handle<my_resource> load(int value) const {
- * // use the integer value somehow
- * return std::make_shared<my_resource>();
- * }
- * };
- * @endcode
- *
- * In general, resource loaders should not have a state or retain data of any
- * type. They should let the cache manage their resources instead.
- *
- * @note
- * Base class and CRTP idiom aren't strictly required with the current
- * implementation. One could argue that a cache can easily work with loaders of
- * any type. However, future changes won't be breaking ones by forcing the use
- * of a base class today and that's why the model is already in its place.
- *
- * @tparam Loader Type of the derived class.
- * @tparam Resource Type of resource for which to use the loader.
- */
- template<typename Loader, typename Resource>
- class resource_loader {
- /*! @brief Resource loaders are friends of their caches. */
- template<typename Other>
- friend struct resource_cache;
- /**
- * @brief Loads the resource and returns it.
- * @tparam Args Types of arguments for the loader.
- * @param args Arguments for the loader.
- * @return The resource just loaded or an empty pointer in case of errors.
- */
- template<typename... Args>
- [[nodiscard]] resource_handle<Resource> get(Args &&... args) const {
- return static_cast<const Loader *>(this)->load(std::forward<Args>(args)...);
- }
- };
- }
- #endif
- // #include "signal/delegate.hpp"
- #ifndef ENTT_SIGNAL_DELEGATE_HPP
- #define ENTT_SIGNAL_DELEGATE_HPP
- #include <tuple>
- #include <cstddef>
- #include <utility>
- #include <functional>
- #include <type_traits>
- // #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
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_NOEXCEPT noexcept
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_NOEXCEPT
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606L
- # include <new>
- # define ENTT_LAUNDER(expr) std::launder(expr)
- #else
- # define ENTT_LAUNDER(expr) expr
- #endif
- #ifndef ENTT_USE_ATOMIC
- # define ENTT_MAYBE_ATOMIC(Type) Type
- #else
- # include <atomic>
- # define ENTT_MAYBE_ATOMIC(Type) std::atomic<Type>
- #endif
- #ifndef ENTT_ID_TYPE
- # include <cstdint>
- # define ENTT_ID_TYPE std::uint32_t
- #endif
- #ifdef ENTT_SPARSE_PAGE
- static_assert(ENTT_SPARSE_PAGE && ((ENTT_SPARSE_PAGE & (ENTT_SPARSE_PAGE - 1)) == 0), "ENTT_SPARSE_PAGE must be a power of two");
- #else
- # define ENTT_SPARSE_PAGE 4096
- #endif
- #ifdef ENTT_PACKED_PAGE
- static_assert(ENTT_PACKED_PAGE && ((ENTT_PACKED_PAGE & (ENTT_PACKED_PAGE - 1)) == 0), "ENTT_PACKED_PAGE must be a power of two");
- #else
- # 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
- # include <type_traits>
- # define ENTT_IGNORE_IF_EMPTY std::false_type
- #else
- # include <type_traits>
- # define ENTT_IGNORE_IF_EMPTY std::true_type
- #endif
- #ifndef ENTT_STANDARD_CPP
- # 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
- #endif
- // #include "fwd.hpp"
- #ifndef ENTT_CORE_FWD_HPP
- #define ENTT_CORE_FWD_HPP
- #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<>;
- }
- #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<class 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_t = 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_v = 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::disjunction_v<std::is_same<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<class 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;
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- namespace internal {
- template<typename>
- [[nodiscard]] constexpr bool is_equality_comparable(...) { return false; }
- template<typename Type>
- [[nodiscard]] constexpr auto is_equality_comparable(choice_t<0>)
- -> decltype(std::declval<Type>() == std::declval<Type>()) { return true; }
- template<typename Type>
- [[nodiscard]] constexpr auto is_equality_comparable(choice_t<1>)
- -> decltype(std::declval<typename Type::value_type>(), std::declval<Type>() == std::declval<Type>()) {
- if constexpr(std::is_same_v<typename Type::value_type, Type>) {
- return is_equality_comparable<Type>(choice<0>);
- } else {
- return is_equality_comparable<typename Type::value_type>(choice<2>);
- }
- }
- template<typename Type>
- [[nodiscard]] constexpr auto is_equality_comparable(choice_t<2>)
- -> decltype(std::declval<typename Type::mapped_type>(), std::declval<Type>() == std::declval<Type>()) {
- return is_equality_comparable<typename Type::key_type>(choice<2>) && is_equality_comparable<typename Type::mapped_type>(choice<2>);
- }
- }
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /**
- * @brief Provides the member constant `value` to true if a given type is
- * equality comparable, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_equality_comparable: std::bool_constant<internal::is_equality_comparable<Type>(choice<2>)> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<class Type>
- inline constexpr bool is_equality_comparable_v = is_equality_comparable<Type>::value;
- /*! @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 {};
- /*! @copydoc is_iterator */
- template<typename Type>
- struct is_iterator<Type, std::void_t<typename std::iterator_traits<Type>::iterator_category>>
- : std::true_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 of the
- * required iterator type, false otherwise.
- * @tparam Type The type to test.
- * @tparam It Required iterator type.
- */
- template<typename Type, typename It, typename = void>
- struct is_iterator_type: std::false_type {};
- /*! @copydoc is_iterator_type */
- template<typename Type, typename It>
- struct is_iterator_type<Type, It, std::enable_if_t<is_iterator_v<Type> && std::is_same_v<Type, It>>>
- : std::true_type
- {};
- /*! @copydoc is_iterator_type */
- template<typename Type, typename It>
- struct is_iterator_type<Type, It, std::enable_if_t<!std::is_same_v<Type, It>, std::void_t<typename It::iterator_type>>>
- : is_iterator_type<Type, typename It::iterator_type>
- {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- * @tparam It Required iterator type.
- */
- template<typename Type, typename It>
- inline constexpr bool is_iterator_type_v = is_iterator_type<Type, It>::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;
- }
- #endif
- // #include "../config/config.h"
- #ifndef ENTT_CONFIG_CONFIG_H
- #define ENTT_CONFIG_CONFIG_H
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_NOEXCEPT noexcept
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_NOEXCEPT
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606L
- # include <new>
- # define ENTT_LAUNDER(expr) std::launder(expr)
- #else
- # define ENTT_LAUNDER(expr) expr
- #endif
- #ifndef ENTT_USE_ATOMIC
- # define ENTT_MAYBE_ATOMIC(Type) Type
- #else
- # include <atomic>
- # define ENTT_MAYBE_ATOMIC(Type) std::atomic<Type>
- #endif
- #ifndef ENTT_ID_TYPE
- # include <cstdint>
- # define ENTT_ID_TYPE std::uint32_t
- #endif
- #ifdef ENTT_SPARSE_PAGE
- static_assert(ENTT_SPARSE_PAGE && ((ENTT_SPARSE_PAGE & (ENTT_SPARSE_PAGE - 1)) == 0), "ENTT_SPARSE_PAGE must be a power of two");
- #else
- # define ENTT_SPARSE_PAGE 4096
- #endif
- #ifdef ENTT_PACKED_PAGE
- static_assert(ENTT_PACKED_PAGE && ((ENTT_PACKED_PAGE & (ENTT_PACKED_PAGE - 1)) == 0), "ENTT_PACKED_PAGE must be a power of two");
- #else
- # 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
- # include <type_traits>
- # define ENTT_IGNORE_IF_EMPTY std::false_type
- #else
- # include <type_traits>
- # define ENTT_IGNORE_IF_EMPTY std::true_type
- #endif
- #ifndef ENTT_STANDARD_CPP
- # 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
- #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...>{};
- }
- }
- /**
- * 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
- : fn{nullptr}, data{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 {
- data = 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 {
- data = &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 {
- data = 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 {
- fn = function;
- data = payload;
- }
- /**
- * @brief Resets a delegate.
- *
- * After a reset, a delegate cannot be invoked anymore.
- */
- void reset() ENTT_NOEXCEPT {
- fn = nullptr;
- data = 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 * instance() const ENTT_NOEXCEPT {
- return data;
- }
- /**
- * @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(data, 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 test also data
- 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 && data == other.data;
- }
- private:
- function_type *fn;
- const void *data;
- };
- /**
- * @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...)>;
- }
- #endif
- // #include "signal/dispatcher.hpp"
- #ifndef ENTT_SIGNAL_DISPATCHER_HPP
- #define ENTT_SIGNAL_DISPATCHER_HPP
- #include <cstddef>
- #include <memory>
- #include <type_traits>
- #include <utility>
- #include <vector>
- // #include "../config/config.h"
- // #include "../core/fwd.hpp"
- #ifndef ENTT_CORE_FWD_HPP
- #define ENTT_CORE_FWD_HPP
- #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<>;
- }
- #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 "../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 "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;
- };
- }
- /**
- * 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 identifers 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.
- *
- * @tparam Char Character type.
- */
- template<typename Char>
- class basic_hashed_string {
- using traits_type = internal::fnv1a_traits<id_type>;
- struct const_wrapper {
- // non-explicit constructor on purpose
- constexpr const_wrapper(const Char *curr) ENTT_NOEXCEPT: str{curr} {}
- const Char *str;
- };
- // Fowler–Noll–Vo hash function v. 1a - the good
- [[nodiscard]] static constexpr id_type helper(const Char *curr) ENTT_NOEXCEPT {
- auto value = traits_type::offset;
- while(*curr != 0) {
- value = (value ^ static_cast<traits_type::type>(*(curr++))) * traits_type::prime;
- }
- return value;
- }
- public:
- /*! @brief Character type. */
- using value_type = Char;
- /*! @brief Unsigned integer type. */
- using hash_type = id_type;
- /**
- * @brief Returns directly the numeric representation of a string view.
- * @param str Human-readable identifer.
- * @param size Length of the string to hash.
- * @return The numeric representation of the string.
- */
- [[nodiscard]] static constexpr hash_type value(const value_type *str, std::size_t size) ENTT_NOEXCEPT {
- id_type partial{traits_type::offset};
- while(size--) { partial = (partial^(str++)[0])*traits_type::prime; }
- return partial;
- }
- /**
- * @brief Returns directly the numeric representation of a string.
- *
- * Forcing template resolution avoids implicit conversions. An
- * human-readable identifier can be anything but a plain, old bunch of
- * characters.<br/>
- * Example of use:
- * @code{.cpp}
- * const auto value = basic_hashed_string<char>::to_value("my.png");
- * @endcode
- *
- * @tparam N Number of characters of the identifier.
- * @param str Human-readable identifer.
- * @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 helper(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 hash_type value(const_wrapper wrapper) ENTT_NOEXCEPT {
- return helper(wrapper.str);
- }
- /*! @brief Constructs an empty hashed string. */
- constexpr basic_hashed_string() ENTT_NOEXCEPT
- : str{nullptr}, hash{}
- {}
- /**
- * @brief Constructs a hashed string from an array of const characters.
- *
- * Forcing template resolution avoids implicit conversions. An
- * human-readable identifier can be anything but a plain, old bunch of
- * characters.<br/>
- * Example of use:
- * @code{.cpp}
- * basic_hashed_string<char> hs{"my.png"};
- * @endcode
- *
- * @tparam N Number of characters of the identifier.
- * @param curr Human-readable identifer.
- */
- template<std::size_t N>
- constexpr basic_hashed_string(const value_type (&curr)[N]) ENTT_NOEXCEPT
- : str{curr}, hash{helper(curr)}
- {}
- /**
- * @brief Explicit constructor on purpose to avoid constructing a hashed
- * string directly from a `const value_type *`.
- * @param wrapper Helps achieving the purpose by relying on overloading.
- */
- explicit constexpr basic_hashed_string(const_wrapper wrapper) ENTT_NOEXCEPT
- : str{wrapper.str}, hash{helper(wrapper.str)}
- {}
- /**
- * @brief Returns the human-readable representation of a hashed string.
- * @return The string used to initialize the instance.
- */
- [[nodiscard]] constexpr const value_type * data() const ENTT_NOEXCEPT {
- return str;
- }
- /**
- * @brief Returns the numeric representation of a hashed string.
- * @return The numeric representation of the instance.
- */
- [[nodiscard]] constexpr hash_type value() const ENTT_NOEXCEPT {
- return 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 instance.
- */
- [[nodiscard]] constexpr operator hash_type() const ENTT_NOEXCEPT { return value(); }
- /**
- * @brief Compares two hashed strings.
- * @param other Hashed string with which to compare.
- * @return True if the two hashed strings are identical, false otherwise.
- */
- [[nodiscard]] constexpr bool operator==(const basic_hashed_string &other) const ENTT_NOEXCEPT {
- return hash == other.hash;
- }
- private:
- const value_type *str;
- hash_type hash;
- };
- /**
- * @brief Deduction guide.
- *
- * It allows to deduce the character type of the hashed string directly from a
- * human-readable identifer provided to the constructor.
- *
- * @tparam Char Character type.
- * @tparam N Number of characters of the identifier.
- * @param str Human-readable identifer.
- */
- 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 == 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 entt::hashed_string operator"" _hs(const char *str, std::size_t) ENTT_NOEXCEPT {
- return entt::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 entt::hashed_wstring operator"" _hws(const wchar_t *str, std::size_t) ENTT_NOEXCEPT {
- return entt::hashed_wstring{str};
- }
- }
- }
- #endif
- // #include "fwd.hpp"
- namespace entt {
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- namespace internal {
- struct ENTT_API type_seq 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;
- }
- }
- /**
- * 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_seq 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_seq::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_seq<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. */
- class type_info final {
- template<typename>
- friend type_info type_id() ENTT_NOEXCEPT;
- type_info(id_type seq_v, id_type hash_v, std::string_view name_v) ENTT_NOEXCEPT
- : seq_value{seq_v},
- hash_value{hash_v},
- name_value{name_v}
- {}
- public:
- /*! @brief Default constructor. */
- type_info() ENTT_NOEXCEPT
- : type_info({}, {}, {})
- {}
- /*! @brief Default copy constructor. */
- type_info(const type_info &) ENTT_NOEXCEPT = default;
- /*! @brief Default move constructor. */
- type_info(type_info &&) ENTT_NOEXCEPT = default;
- /**
- * @brief Default copy assignment operator.
- * @return This type info object.
- */
- type_info & operator=(const type_info &) ENTT_NOEXCEPT = default;
- /**
- * @brief Default move assignment operator.
- * @return This type info object.
- */
- type_info & operator=(type_info &&) ENTT_NOEXCEPT = default;
- /**
- * @brief Checks if a type info object is properly initialized.
- * @return True if the object is properly initialized, false otherwise.
- */
- [[nodiscard]] explicit operator bool() const ENTT_NOEXCEPT {
- return name_value.data() != nullptr;
- }
- /**
- * @brief Type sequential identifier.
- * @return Type sequential identifier.
- */
- [[nodiscard]] id_type seq() const ENTT_NOEXCEPT {
- return seq_value;
- }
- /**
- * @brief Type hash.
- * @return Type hash.
- */
- [[nodiscard]] id_type hash() const ENTT_NOEXCEPT {
- return hash_value;
- }
- /**
- * @brief Type name.
- * @return Type name.
- */
- [[nodiscard]] std::string_view name() const ENTT_NOEXCEPT {
- return name_value;
- }
- /**
- * @brief Compares the contents of two type info objects.
- * @param other Object with which to compare.
- * @return False if the two contents differ, true otherwise.
- */
- [[nodiscard]] bool operator==(const type_info &other) const ENTT_NOEXCEPT {
- return hash_value == other.hash_value;
- }
- private:
- id_type seq_value;
- id_type hash_value;
- std::string_view name_value;
- };
- /**
- * @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 contents differ, false otherwise.
- */
- [[nodiscard]] inline bool operator!=(const type_info &lhs, const type_info &rhs) ENTT_NOEXCEPT {
- return !(lhs == rhs);
- }
- /**
- * @brief Returns the type info object for a given type.
- * @tparam Type Type for which to generate a type info object.
- * @return The type info object for the given type.
- */
- template<typename Type>
- [[nodiscard]] type_info type_id() ENTT_NOEXCEPT {
- return type_info{
- type_seq<std::remove_cv_t<std::remove_reference_t<Type>>>::value(),
- type_hash<std::remove_cv_t<std::remove_reference_t<Type>>>::value(),
- type_name<std::remove_cv_t<std::remove_reference_t<Type>>>::value()
- };
- }
- }
- #endif
- // #include "sigh.hpp"
- #ifndef ENTT_SIGNAL_SIGH_HPP
- #define ENTT_SIGNAL_SIGH_HPP
- #include <vector>
- #include <utility>
- #include <iterator>
- #include <algorithm>
- #include <functional>
- #include <type_traits>
- // #include "../config/config.h"
- // #include "delegate.hpp"
- #ifndef ENTT_SIGNAL_DELEGATE_HPP
- #define ENTT_SIGNAL_DELEGATE_HPP
- #include <tuple>
- #include <cstddef>
- #include <utility>
- #include <functional>
- #include <type_traits>
- // #include "../core/type_traits.hpp"
- // #include "../config/config.h"
- 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...>{};
- }
- }
- /**
- * 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
- : fn{nullptr}, data{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 {
- data = 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 {
- data = &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 {
- data = 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 {
- fn = function;
- data = payload;
- }
- /**
- * @brief Resets a delegate.
- *
- * After a reset, a delegate cannot be invoked anymore.
- */
- void reset() ENTT_NOEXCEPT {
- fn = nullptr;
- data = 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 * instance() const ENTT_NOEXCEPT {
- return data;
- }
- /**
- * @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(data, 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 test also data
- 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 && data == other.data;
- }
- private:
- function_type *fn;
- const void *data;
- };
- /**
- * @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...)>;
- }
- #endif
- // #include "fwd.hpp"
- #ifndef ENTT_SIGNAL_FWD_HPP
- #define ENTT_SIGNAL_FWD_HPP
- namespace entt {
- template<typename>
- class delegate;
- class dispatcher;
- template<typename>
- class emitter;
- class connection;
- struct scoped_connection;
- template<typename>
- class sink;
- template<typename>
- class sigh;
- }
- #endif
- 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 Function A valid function type.
- */
- template<typename Function>
- 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 Function A valid function type.
- */
- template<typename Function>
- 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.
- */
- template<typename Ret, typename... Args>
- class sigh<Ret(Args...)> {
- /*! @brief A sink is allowed to modify a signal. */
- friend class sink<Ret(Args...)>;
- public:
- /*! @brief Unsigned integer type. */
- using size_type = std::size_t;
- /*! @brief Sink type. */
- using sink_type = sink<Ret(Args...)>;
- /**
- * @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:
- std::vector<delegate<Ret(Args...)>> 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 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 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.
- */
- template<typename Ret, typename... Args>
- class sink<Ret(Args...)> {
- using signal_type = sigh<Ret(Args...)>;
- using difference_type = typename std::iterator_traits<typename decltype(signal_type::calls)::iterator>::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...)> &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 = std::distance(it, calls.cend());
- 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 = std::distance(it, calls.cend());
- 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.instance() == value_or_instance;
- });
- other.offset = std::distance(it, calls.cend());
- }
- 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;
- calls.erase(std::remove_if(calls.begin(), calls.end(), [value_or_instance](const auto &delegate) {
- return delegate.instance() == value_or_instance;
- }), 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 function 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.
- */
- template<typename Ret, typename... Args>
- sink(sigh<Ret(Args...)> &)
- -> sink<Ret(Args...)>;
- }
- #endif
- namespace entt {
- /**
- * @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.
- */
- class dispatcher {
- struct basic_pool {
- virtual ~basic_pool() = default;
- virtual void publish() = 0;
- virtual void disconnect(void *) = 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 signal_type = sigh<void(Event &)>;
- using sink_type = typename signal_type::sink_type;
- 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 {
- sink().disconnect(instance);
- }
- void clear() ENTT_NOEXCEPT override {
- events.clear();
- }
- [[nodiscard]] sink_type sink() ENTT_NOEXCEPT {
- return entt::sink{signal};
- }
- template<typename... Args>
- void trigger(Args &&... args) {
- Event instance{std::forward<Args>(args)...};
- signal.publish(instance);
- }
- 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)...);
- }
- }
- private:
- signal_type signal{};
- std::vector<Event> events;
- };
- template<typename Event>
- [[nodiscard]] pool_handler<Event> & assure() {
- const auto index = type_seq<Event>::value();
- if(!(index < pools.size())) {
- pools.resize(std::size_t(index)+1u);
- }
- if(!pools[index]) {
- pools[index].reset(new pool_handler<Event>{});
- }
- return static_cast<pool_handler<Event> &>(*pools[index]);
- }
- public:
- /*! @brief Default constructor. */
- dispatcher() = default;
- /*! @brief Default move constructor. */
- dispatcher(dispatcher &&) = default;
- /*! @brief Default move assignment operator. @return This dispatcher. */
- dispatcher & operator=(dispatcher &&) = default;
- /**
- * @brief Returns a sink object for the given event.
- *
- * 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.
- * @return A temporary sink object.
- */
- template<typename Event>
- [[nodiscard]] auto sink() {
- return assure<Event>().sink();
- }
- /**
- * @brief Triggers an immediate event of the given type.
- *
- * All the listeners registered for the given type are immediately notified.
- * The event is discarded after the execution.
- *
- * @tparam Event Type of event to trigger.
- * @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 trigger(Args &&... args) {
- assure<Event>().trigger(std::forward<Args>(args)...);
- }
- /**
- * @brief Triggers an immediate event of the given type.
- *
- * All the listeners registered for the given type are immediately notified.
- * The event is discarded after the execution.
- *
- * @tparam Event Type of event to trigger.
- * @param event An instance of the given type of event.
- */
- template<typename Event>
- void trigger(Event &&event) {
- assure<std::decay_t<Event>>().trigger(std::forward<Event>(event));
- }
- /**
- * @brief Enqueues an event of the given type.
- *
- * An event of the given type is queued. No listener is invoked. Use the
- * `update` member function to notify listeners when ready.
- *
- * @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) {
- assure<Event>().enqueue(std::forward<Args>(args)...);
- }
- /**
- * @brief Enqueues an event of the given type.
- *
- * An event of the given type is queued. No listener is invoked. Use the
- * `update` member function to notify listeners when ready.
- *
- * @tparam Event Type of event to enqueue.
- * @param event An instance of the given type of event.
- */
- template<typename Event>
- void enqueue(Event &&event) {
- assure<std::decay_t<Event>>().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) {
- if(cpool) {
- cpool->disconnect(value_or_instance);
- }
- }
- }
- /**
- * @brief Discards all the events queued so far.
- *
- * If no types are provided, the dispatcher will clear all the existing
- * pools.
- *
- * @tparam Event Type of events to discard.
- */
- template<typename... Event>
- void clear() {
- if constexpr(sizeof...(Event) == 0) {
- for(auto &&cpool: pools) {
- if(cpool) {
- cpool->clear();
- }
- }
- } else {
- (assure<Event>().clear(), ...);
- }
- }
- /**
- * @brief Delivers all the pending events of the given type.
- *
- * This method is blocking and it doesn't return until all the events are
- * delivered to the registered listeners. It's responsibility of the users
- * to reduce at a minimum the time spent in the bodies of the listeners.
- *
- * @tparam Event Type of events to send.
- */
- template<typename Event>
- void update() {
- assure<Event>().publish();
- }
- /**
- * @brief Delivers all the pending events.
- *
- * This method is blocking and it doesn't return until all the events are
- * delivered to the registered listeners. It's responsibility of the users
- * to reduce at a minimum the time spent in the bodies of the listeners.
- */
- void update() const {
- for(auto pos = pools.size(); pos; --pos) {
- if(auto &&cpool = pools[pos-1]; cpool) {
- cpool->publish();
- }
- }
- }
- private:
- std::vector<std::unique_ptr<basic_pool>> pools;
- };
- }
- #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 <vector>
- // #include "../config/config.h"
- // #include "../core/fwd.hpp"
- // #include "../core/type_info.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() {
- const auto index = type_seq<Event>::value();
- if(!(index < pools.size())) {
- pools.resize(std::size_t(index)+1u);
- }
- if(!pools[index]) {
- pools[index].reset(new pool_handler<Event>{});
- }
- return static_cast<pool_handler<Event> *>(pools[index].get());
- }
- template<typename Event>
- [[nodiscard]] const pool_handler<Event> * assure() const {
- const auto index = type_seq<Event>::value();
- return (!(index < pools.size()) || !pools[index]) ? nullptr : static_cast<const pool_handler<Event> *>(pools[index].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() = 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() {
- 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) {
- if(cpool) {
- cpool->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 || cpool->empty();
- });
- }
- private:
- std::vector<std::unique_ptr<basic_pool>> pools{};
- };
- }
- #endif
- // #include "signal/sigh.hpp"
- #ifndef ENTT_SIGNAL_SIGH_HPP
- #define ENTT_SIGNAL_SIGH_HPP
- #include <vector>
- #include <utility>
- #include <iterator>
- #include <algorithm>
- #include <functional>
- #include <type_traits>
- // #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 Function A valid function type.
- */
- template<typename Function>
- 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 Function A valid function type.
- */
- template<typename Function>
- 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.
- */
- template<typename Ret, typename... Args>
- class sigh<Ret(Args...)> {
- /*! @brief A sink is allowed to modify a signal. */
- friend class sink<Ret(Args...)>;
- public:
- /*! @brief Unsigned integer type. */
- using size_type = std::size_t;
- /*! @brief Sink type. */
- using sink_type = sink<Ret(Args...)>;
- /**
- * @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:
- std::vector<delegate<Ret(Args...)>> 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 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 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.
- */
- template<typename Ret, typename... Args>
- class sink<Ret(Args...)> {
- using signal_type = sigh<Ret(Args...)>;
- using difference_type = typename std::iterator_traits<typename decltype(signal_type::calls)::iterator>::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...)> &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 = std::distance(it, calls.cend());
- 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 = std::distance(it, calls.cend());
- 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.instance() == value_or_instance;
- });
- other.offset = std::distance(it, calls.cend());
- }
- 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;
- calls.erase(std::remove_if(calls.begin(), calls.end(), [value_or_instance](const auto &delegate) {
- return delegate.instance() == value_or_instance;
- }), 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 function 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.
- */
- template<typename Ret, typename... Args>
- sink(sigh<Ret(Args...)> &)
- -> sink<Ret(Args...)>;
- }
- #endif
|