|
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940 |
- /// \file meta.hpp Tiny meta-programming library.
- //
- // Meta library
- //
- // Copyright Eric Niebler 2014-present
- //
- // Use, modification and distribution is subject to the
- // Boost Software License, Version 1.0. (See accompanying
- // file LICENSE_1_0.txt or copy at
- // http://www.boost.org/LICENSE_1_0.txt)
- //
- // Project home: https://github.com/ericniebler/meta
- //
-
- #ifndef META_HPP
- #define META_HPP
-
- #include <cstddef>
- #include <initializer_list>
- #include <meta/meta_fwd.hpp>
- #include <type_traits>
- #include <utility>
-
- #ifdef __clang__
- #pragma GCC diagnostic push
- #pragma GCC diagnostic ignored "-Wunknown-pragmas"
- #pragma GCC diagnostic ignored "-Wpragmas"
- #pragma GCC diagnostic ignored "-Wdocumentation-deprecated-sync"
- #pragma GCC diagnostic ignored "-Wmissing-variable-declarations"
- #endif
-
- /// \defgroup meta Meta
- ///
- /// A tiny metaprogramming library
-
- /// \defgroup trait Trait
- /// Trait invocation/composition.
- /// \ingroup meta
-
- /// \defgroup invocation Invocation
- /// Trait invocation
- /// \ingroup trait
-
- /// \defgroup composition Composition
- /// Trait composition
- /// \ingroup trait
-
- /// \defgroup logical Logical
- /// Logical operations
- /// \ingroup meta
-
- /// \defgroup algorithm Algorithms
- /// Algorithms.
- /// \ingroup meta
-
- /// \defgroup query Query/Search
- /// Query and search algorithms
- /// \ingroup algorithm
-
- /// \defgroup transformation Transformation
- /// Transformation algorithms
- /// \ingroup algorithm
-
- /// \defgroup runtime Runtime
- /// Runtime algorithms
- /// \ingroup algorithm
-
- /// \defgroup datatype Datatype
- /// Datatypes.
- /// \ingroup meta
-
- /// \defgroup list list_like
- /// \ingroup datatype
-
- /// \defgroup integral Integer sequence
- /// Equivalent to C++14's `std::integer_sequence`
- /// \ingroup datatype
-
- /// \defgroup extension Extension
- /// Extend meta with your own datatypes.
- /// \ingroup datatype
-
- /// \defgroup math Math
- /// Integral constant arithmetic.
- /// \ingroup meta
-
- /// \defgroup lazy_trait lazy
- /// \ingroup trait
-
- /// \defgroup lazy_invocation lazy
- /// \ingroup invocation
-
- /// \defgroup lazy_composition lazy
- /// \ingroup composition
-
- /// \defgroup lazy_logical lazy
- /// \ingroup logical
-
- /// \defgroup lazy_query lazy
- /// \ingroup query
-
- /// \defgroup lazy_transformation lazy
- /// \ingroup transformation
-
- /// \defgroup lazy_list lazy
- /// \ingroup list
-
- /// \defgroup lazy_datatype lazy
- /// \ingroup datatype
-
- /// \defgroup lazy_math lazy
- /// \ingroup math
-
- /// Tiny metaprogramming library
- namespace meta
- {
- namespace detail
- {
- /// Returns a \p T nullptr
- template <typename T>
- constexpr T *_nullptr_v()
- {
- return nullptr;
- }
-
- #if META_CXX_VARIABLE_TEMPLATES
- template <typename T>
- META_INLINE_VAR constexpr T *nullptr_v = nullptr;
- #endif
- } // namespace detail
-
- /// An empty type.
- /// \ingroup datatype
- struct nil_
- {
- };
-
- /// Type alias for \p T::type.
- /// \ingroup invocation
- template <META_TYPE_CONSTRAINT(trait) T>
- using _t = typename T::type;
-
- #if META_CXX_VARIABLE_TEMPLATES || defined(META_DOXYGEN_INVOKED)
- /// Variable alias for \c T::type::value
- /// \note Requires C++14 or greater.
- /// \ingroup invocation
- template <META_TYPE_CONSTRAINT(integral) T>
- constexpr typename T::type::value_type _v = T::type::value;
- #endif
-
- /// Lazy versions of meta actions
- namespace lazy
- {
- /// \sa `meta::_t`
- /// \ingroup lazy_invocation
- template <typename T>
- using _t = defer<_t, T>;
- } // namespace lazy
-
- /// An integral constant wrapper for \c std::size_t.
- /// \ingroup integral
- template <std::size_t N>
- using size_t = std::integral_constant<std::size_t, N>;
-
- /// An integral constant wrapper for \c bool.
- /// \ingroup integral
- template <bool B>
- using bool_ = std::integral_constant<bool, B>;
-
- /// An integral constant wrapper for \c int.
- /// \ingroup integral
- template <int I>
- using int_ = std::integral_constant<int, I>;
-
- /// An integral constant wrapper for \c char.
- /// \ingroup integral
- template <char Ch>
- using char_ = std::integral_constant<char, Ch>;
-
- ///////////////////////////////////////////////////////////////////////////////////////////
- // Math operations
- /// An integral constant wrapper around the result of incrementing the wrapped integer \c
- /// T::type::value.
- template <META_TYPE_CONSTRAINT(integral) T>
- using inc = std::integral_constant<decltype(T::type::value + 1), T::type::value + 1>;
-
- /// An integral constant wrapper around the result of decrementing the wrapped integer \c
- /// T::type::value.
- template <META_TYPE_CONSTRAINT(integral) T>
- using dec = std::integral_constant<decltype(T::type::value - 1), T::type::value - 1>;
-
- /// An integral constant wrapper around the result of adding the two wrapped integers
- /// \c T::type::value and \c U::type::value.
- /// \ingroup math
- template <META_TYPE_CONSTRAINT(integral) T, META_TYPE_CONSTRAINT(integral) U>
- using plus = std::integral_constant<decltype(T::type::value + U::type::value),
- T::type::value + U::type::value>;
-
- /// An integral constant wrapper around the result of subtracting the two wrapped integers
- /// \c T::type::value and \c U::type::value.
- /// \ingroup math
- template <META_TYPE_CONSTRAINT(integral) T, META_TYPE_CONSTRAINT(integral) U>
- using minus = std::integral_constant<decltype(T::type::value - U::type::value),
- T::type::value - U::type::value>;
-
- /// An integral constant wrapper around the result of multiplying the two wrapped integers
- /// \c T::type::value and \c U::type::value.
- /// \ingroup math
- template <META_TYPE_CONSTRAINT(integral) T, META_TYPE_CONSTRAINT(integral) U>
- using multiplies = std::integral_constant<decltype(T::type::value * U::type::value),
- T::type::value * U::type::value>;
-
- /// An integral constant wrapper around the result of dividing the two wrapped integers \c
- /// T::type::value and \c U::type::value.
- /// \ingroup math
- template <META_TYPE_CONSTRAINT(integral) T, META_TYPE_CONSTRAINT(integral) U>
- using divides = std::integral_constant<decltype(T::type::value / U::type::value),
- T::type::value / U::type::value>;
-
- /// An integral constant wrapper around the result of negating the wrapped integer
- /// \c T::type::value.
- /// \ingroup math
- template <META_TYPE_CONSTRAINT(integral) T>
- using negate = std::integral_constant<decltype(-T::type::value), -T::type::value>;
-
- /// An integral constant wrapper around the remainder of dividing the two wrapped integers
- /// \c T::type::value and \c U::type::value.
- /// \ingroup math
- template <META_TYPE_CONSTRAINT(integral) T, META_TYPE_CONSTRAINT(integral) U>
- using modulus = std::integral_constant<decltype(T::type::value % U::type::value),
- T::type::value % U::type::value>;
-
- /// A Boolean integral constant wrapper around the result of comparing \c T::type::value and
- /// \c U::type::value for equality.
- /// \ingroup math
- template <META_TYPE_CONSTRAINT(integral) T, META_TYPE_CONSTRAINT(integral) U>
- using equal_to = bool_<T::type::value == U::type::value>;
-
- /// A Boolean integral constant wrapper around the result of comparing \c T::type::value and
- /// \c U::type::value for inequality.
- /// \ingroup math
- template <META_TYPE_CONSTRAINT(integral) T, META_TYPE_CONSTRAINT(integral) U>
- using not_equal_to = bool_<T::type::value != U::type::value>;
-
- /// A Boolean integral constant wrapper around \c true if \c T::type::value is greater than
- /// \c U::type::value; \c false, otherwise.
- /// \ingroup math
- template <META_TYPE_CONSTRAINT(integral) T, META_TYPE_CONSTRAINT(integral) U>
- using greater = bool_<(T::type::value > U::type::value)>;
-
- /// A Boolean integral constant wrapper around \c true if \c T::type::value is less than \c
- /// U::type::value; \c false, otherwise.
- /// \ingroup math
- template <META_TYPE_CONSTRAINT(integral) T, META_TYPE_CONSTRAINT(integral) U>
- using less = bool_<(T::type::value < U::type::value)>;
-
- /// A Boolean integral constant wrapper around \c true if \c T::type::value is greater than
- /// or equal to \c U::type::value; \c false, otherwise.
- /// \ingroup math
- template <META_TYPE_CONSTRAINT(integral) T, META_TYPE_CONSTRAINT(integral) U>
- using greater_equal = bool_<(T::type::value >= U::type::value)>;
-
- /// A Boolean integral constant wrapper around \c true if \c T::type::value is less than or
- /// equal to \c U::type::value; \c false, otherwise.
- /// \ingroup math
- template <META_TYPE_CONSTRAINT(integral) T, META_TYPE_CONSTRAINT(integral) U>
- using less_equal = bool_<(T::type::value <= U::type::value)>;
-
- /// An integral constant wrapper around the result of bitwise-and'ing the two wrapped
- /// integers \c T::type::value and \c U::type::value.
- /// \ingroup math
- template <META_TYPE_CONSTRAINT(integral) T, META_TYPE_CONSTRAINT(integral) U>
- using bit_and = std::integral_constant<decltype(T::type::value & U::type::value),
- T::type::value & U::type::value>;
-
- /// An integral constant wrapper around the result of bitwise-or'ing the two wrapped
- /// integers \c T::type::value and \c U::type::value.
- /// \ingroup math
- template <META_TYPE_CONSTRAINT(integral) T, META_TYPE_CONSTRAINT(integral) U>
- using bit_or = std::integral_constant<decltype(T::type::value | U::type::value),
- T::type::value | U::type::value>;
-
- /// An integral constant wrapper around the result of bitwise-exclusive-or'ing the two
- /// wrapped integers \c T::type::value and \c U::type::value.
- /// \ingroup math
- template <META_TYPE_CONSTRAINT(integral) T, META_TYPE_CONSTRAINT(integral) U>
- using bit_xor = std::integral_constant<decltype(T::type::value ^ U::type::value),
- T::type::value ^ U::type::value>;
-
- /// An integral constant wrapper around the result of bitwise-complementing the wrapped
- /// integer \c T::type::value.
- /// \ingroup math
- template <META_TYPE_CONSTRAINT(integral) T>
- using bit_not = std::integral_constant<decltype(~T::type::value), ~T::type::value>;
-
- namespace lazy
- {
- /// \sa 'meta::int'
- /// \ingroup lazy_math
- template <typename T>
- using inc = defer<inc, T>;
-
- /// \sa 'meta::dec'
- /// \ingroup lazy_math
- template <typename T>
- using dec = defer<dec, T>;
-
- /// \sa 'meta::plus'
- /// \ingroup lazy_math
- template <typename T, typename U>
- using plus = defer<plus, T, U>;
-
- /// \sa 'meta::minus'
- /// \ingroup lazy_math
- template <typename T, typename U>
- using minus = defer<minus, T, U>;
-
- /// \sa 'meta::multiplies'
- /// \ingroup lazy_math
- template <typename T, typename U>
- using multiplies = defer<multiplies, T, U>;
-
- /// \sa 'meta::divides'
- /// \ingroup lazy_math
- template <typename T, typename U>
- using divides = defer<divides, T, U>;
-
- /// \sa 'meta::negate'
- /// \ingroup lazy_math
- template <typename T>
- using negate = defer<negate, T>;
-
- /// \sa 'meta::modulus'
- /// \ingroup lazy_math
- template <typename T, typename U>
- using modulus = defer<modulus, T, U>;
-
- /// \sa 'meta::equal_to'
- /// \ingroup lazy_math
- template <typename T, typename U>
- using equal_to = defer<equal_to, T, U>;
-
- /// \sa 'meta::not_equal_t'
- /// \ingroup lazy_math
- template <typename T, typename U>
- using not_equal_to = defer<not_equal_to, T, U>;
-
- /// \sa 'meta::greater'
- /// \ingroup lazy_math
- template <typename T, typename U>
- using greater = defer<greater, T, U>;
-
- /// \sa 'meta::less'
- /// \ingroup lazy_math
- template <typename T, typename U>
- using less = defer<less, T, U>;
-
- /// \sa 'meta::greater_equal'
- /// \ingroup lazy_math
- template <typename T, typename U>
- using greater_equal = defer<greater_equal, T, U>;
-
- /// \sa 'meta::less_equal'
- /// \ingroup lazy_math
- template <typename T, typename U>
- using less_equal = defer<less_equal, T, U>;
-
- /// \sa 'meta::bit_and'
- /// \ingroup lazy_math
- template <typename T, typename U>
- using bit_and = defer<bit_and, T, U>;
-
- /// \sa 'meta::bit_or'
- /// \ingroup lazy_math
- template <typename T, typename U>
- using bit_or = defer<bit_or, T, U>;
-
- /// \sa 'meta::bit_xor'
- /// \ingroup lazy_math
- template <typename T, typename U>
- using bit_xor = defer<bit_xor, T, U>;
-
- /// \sa 'meta::bit_not'
- /// \ingroup lazy_math
- template <typename T>
- using bit_not = defer<bit_not, T>;
- } // namespace lazy
-
- /// \cond
- namespace detail
- {
- enum class indices_strategy_
- {
- done,
- repeat,
- recurse
- };
-
- constexpr indices_strategy_ strategy_(std::size_t cur, std::size_t end)
- {
- return cur >= end ? indices_strategy_::done
- : cur * 2 <= end ? indices_strategy_::repeat
- : indices_strategy_::recurse;
- }
-
- template <typename T>
- constexpr std::size_t range_distance_(T begin, T end)
- {
- return begin <= end ? static_cast<std::size_t>(end - begin)
- : throw "The start of the integer_sequence must not be "
- "greater than the end";
- }
-
- template <std::size_t End, typename State, indices_strategy_ Status_>
- struct make_indices_
- {
- using type = State;
- };
-
- template <typename T, T, typename>
- struct coerce_indices_
- {
- };
- } // namespace detail
- /// \endcond
-
- ///////////////////////////////////////////////////////////////////////////////////////////
- // integer_sequence
- #if !META_CXX_INTEGER_SEQUENCE
- /// A container for a sequence of compile-time integer constants.
- /// \ingroup integral
- template <typename T, T... Is>
- struct integer_sequence
- {
- using value_type = T;
- /// \return `sizeof...(Is)`
- static constexpr std::size_t size() noexcept { return sizeof...(Is); }
- };
- #endif
-
- ///////////////////////////////////////////////////////////////////////////////////////////
- // index_sequence
- /// A container for a sequence of compile-time integer constants of type
- /// \c std::size_t
- /// \ingroup integral
- template <std::size_t... Is>
- using index_sequence = integer_sequence<std::size_t, Is...>;
-
- #if META_HAS_MAKE_INTEGER_SEQ && !defined(META_DOXYGEN_INVOKED)
- // Implement make_integer_sequence and make_index_sequence with the
- // __make_integer_seq builtin on compilers that provide it. (Redirect
- // through decltype to workaround suspected clang bug.)
- /// \cond
- namespace detail
- {
- template <typename T, T N>
- __make_integer_seq<integer_sequence, T, N> make_integer_sequence_();
- }
- /// \endcond
-
- template <typename T, T N>
- using make_integer_sequence = decltype(detail::make_integer_sequence_<T, N>());
-
- template <std::size_t N>
- using make_index_sequence = make_integer_sequence<std::size_t, N>;
- #else
- /// Generate \c index_sequence containing integer constants [0,1,2,...,N-1].
- /// \par Complexity
- /// \f$ O(log(N)) \f$.
- /// \ingroup integral
- template <std::size_t N>
- using make_index_sequence =
- _t<detail::make_indices_<N, index_sequence<0>, detail::strategy_(1, N)>>;
-
- /// Generate \c integer_sequence containing integer constants [0,1,2,...,N-1].
- /// \par Complexity
- /// \f$ O(log(N)) \f$.
- /// \ingroup integral
- template <typename T, T N>
- using make_integer_sequence =
- _t<detail::coerce_indices_<T, 0, make_index_sequence<static_cast<std::size_t>(N)>>>;
- #endif
-
- ///////////////////////////////////////////////////////////////////////////////////////////
- // integer_range
- /// Makes the integer sequence <tt>[From, To)</tt>.
- /// \par Complexity
- /// \f$ O(log(To - From)) \f$.
- /// \ingroup integral
- template <typename T, T From, T To>
- using integer_range =
- _t<detail::coerce_indices_<T, From,
- make_index_sequence<detail::range_distance_(From, To)>>>;
-
- /// \cond
- namespace detail
- {
- template <typename, typename>
- struct concat_indices_
- {
- };
-
- template <std::size_t... Is, std::size_t... Js>
- struct concat_indices_<index_sequence<Is...>, index_sequence<Js...>>
- {
- using type = index_sequence<Is..., (Js + sizeof...(Is))...>;
- };
-
- template <>
- struct make_indices_<0u, index_sequence<0>, indices_strategy_::done>
- {
- using type = index_sequence<>;
- };
-
- template <std::size_t End, std::size_t... Values>
- struct make_indices_<End, index_sequence<Values...>, indices_strategy_::repeat>
- : make_indices_<End, index_sequence<Values..., (Values + sizeof...(Values))...>,
- detail::strategy_(sizeof...(Values) * 2, End)>
- {
- };
-
- template <std::size_t End, std::size_t... Values>
- struct make_indices_<End, index_sequence<Values...>, indices_strategy_::recurse>
- : concat_indices_<index_sequence<Values...>,
- make_index_sequence<End - sizeof...(Values)>>
- {
- };
-
- template <typename T, T Offset, std::size_t... Values>
- struct coerce_indices_<T, Offset, index_sequence<Values...>>
- {
- using type =
- integer_sequence<T, static_cast<T>(static_cast<T>(Values) + Offset)...>;
- };
- } // namespace detail
- /// \endcond
-
- /// Evaluate the invocable \p Fn with the arguments \p Args.
- /// \ingroup invocation
- template <META_TYPE_CONSTRAINT(invocable) Fn, typename... Args>
- using invoke = typename Fn::template invoke<Args...>;
-
- /// Lazy versions of meta actions
- namespace lazy
- {
- /// \sa `meta::invoke`
- /// \ingroup lazy_invocation
- template <typename Fn, typename... Args>
- using invoke = defer<invoke, Fn, Args...>;
- } // namespace lazy
-
- /// A trait that always returns its argument \p T. It is also an invocable
- /// that always returns \p T.
- /// \ingroup trait
- /// \ingroup invocation
- template <typename T>
- struct id
- {
- #if defined(META_WORKAROUND_CWG_1558) && !defined(META_DOXYGEN_INVOKED)
- // Redirect through decltype for compilers that have not
- // yet implemented CWG 1558:
- static id impl(void *);
-
- template <typename... Ts>
- using invoke = _t<decltype(id::impl(static_cast<list<Ts...> *>(nullptr)))>;
- #else
- template <typename...>
- using invoke = T;
- #endif
-
- using type = T;
- };
-
- /// An alias for type \p T. Useful in non-deduced contexts.
- /// \ingroup trait
- template <typename T>
- using id_t = _t<id<T>>;
-
- namespace lazy
- {
- /// \sa `meta::id`
- /// \ingroup lazy_trait
- /// \ingroup lazy_invocation
- template <typename T>
- using id = defer<id, T>;
- } // namespace lazy
-
- /// An alias for `void`.
- /// \ingroup trait
- #if defined(META_WORKAROUND_CWG_1558) && !defined(META_DOXYGEN_INVOKED)
- // Redirect through decltype for compilers that have not
- // yet implemented CWG 1558:
- template <typename... Ts>
- using void_ = invoke<id<void>, Ts...>;
- #else
- template <typename...>
- using void_ = void;
- #endif
-
- #if META_CXX_VARIABLE_TEMPLATES
- #ifdef META_CONCEPT
- /// `true` if `T::type` exists and names a type; `false` otherwise.
- /// \ingroup trait
- template <typename T>
- META_INLINE_VAR constexpr bool is_trait_v = trait<T>;
-
- /// `true` if `T::invoke` exists and names a class template; `false` otherwise.
- /// \ingroup trait
- template <typename T>
- META_INLINE_VAR constexpr bool is_callable_v = invocable<T>;
- #else // ^^^ Concepts / No concepts vvv
- /// \cond
- namespace detail
- {
- template <typename, typename = void>
- META_INLINE_VAR constexpr bool is_trait_ = false;
-
- template <typename T>
- META_INLINE_VAR constexpr bool is_trait_<T, void_<typename T::type>> = true;
-
- template <typename, typename = void>
- META_INLINE_VAR constexpr bool is_callable_ = false;
-
- template <typename T>
- META_INLINE_VAR constexpr bool is_callable_<T, void_<quote<T::template invoke>>> = true;
- } // namespace detail
- /// \endcond
-
- /// `true` if `T::type` exists and names a type; `false` otherwise.
- /// \ingroup trait
- template <typename T>
- META_INLINE_VAR constexpr bool is_trait_v = detail::is_trait_<T>;
-
- /// `true` if `T::invoke` exists and names a class template; `false` otherwise.
- /// \ingroup trait
- template <typename T>
- META_INLINE_VAR constexpr bool is_callable_v = detail::is_callable_<T>;
- #endif // Concepts vs. variable templates
-
- /// An alias for `std::true_type` if `T::type` exists and names a type; otherwise, it's an
- /// alias for `std::false_type`.
- /// \ingroup trait
- template <typename T>
- using is_trait = bool_<is_trait_v<T>>;
-
- /// An alias for `std::true_type` if `T::invoke` exists and names a class template;
- /// otherwise, it's an alias for `std::false_type`.
- /// \ingroup trait
- template <typename T>
- using is_callable = bool_<is_callable_v<T>>;
- #else // ^^^ META_CXX_VARIABLE_TEMPLATES / !META_CXX_VARIABLE_TEMPLATES vvv
- /// \cond
- namespace detail
- {
- template <typename, typename = void>
- struct is_trait_
- {
- using type = std::false_type;
- };
-
- template <typename T>
- struct is_trait_<T, void_<typename T::type>>
- {
- using type = std::true_type;
- };
-
- template <typename, typename = void>
- struct is_callable_
- {
- using type = std::false_type;
- };
-
- template <typename T>
- struct is_callable_<T, void_<quote<T::template invoke>>>
- {
- using type = std::true_type;
- };
- } // namespace detail
- /// \endcond
-
- template <typename T>
- using is_trait = _t<detail::is_trait_<T>>;
-
- /// An alias for `std::true_type` if `T::invoke` exists and names a class
- /// template or alias template; otherwise, it's an alias for
- /// `std::false_type`.
- /// \ingroup trait
- template <typename T>
- using is_callable = _t<detail::is_callable_<T>>;
- #endif
-
- /// \cond
- namespace detail
- {
- #ifdef META_CONCEPT
- template <template <typename...> class, typename...>
- struct defer_
- {
- };
-
- template <template <typename...> class C, typename... Ts>
- requires valid<C, Ts...> struct defer_<C, Ts...>
- {
- using type = C<Ts...>;
- };
-
- template <typename T, template <T...> class, T...>
- struct defer_i_
- {
- };
-
- template <typename T, template <T...> class C, T... Is>
- requires valid_i<T, C, Is...> struct defer_i_<T, C, Is...>
- {
- using type = C<Is...>;
- };
- #elif defined(META_WORKAROUND_MSVC_703656) // ^^^ Concepts / MSVC workaround vvv
- template <typename, template <typename...> class, typename...>
- struct _defer_
- {
- };
-
- template <template <typename...> class C, typename... Ts>
- struct _defer_<void_<C<Ts...>>, C, Ts...>
- {
- using type = C<Ts...>;
- };
-
- template <template <typename...> class C, typename... Ts>
- using defer_ = _defer_<void, C, Ts...>;
-
- template <typename, typename T, template <T...> class, T...>
- struct _defer_i_
- {
- };
-
- template <typename T, template <T...> class C, T... Is>
- struct _defer_i_<void_<C<Is...>>, T, C, Is...>
- {
- using type = C<Is...>;
- };
-
- template <typename T, template <T...> class C, T... Is>
- using defer_i_ = _defer_i_<void, T, C, Is...>;
- #else // ^^^ workaround ^^^ / vvv no workaround vvv
- template <template <typename...> class C, typename... Ts,
- template <typename...> class D = C>
- id<D<Ts...>> try_defer_(int);
- template <template <typename...> class C, typename... Ts>
- nil_ try_defer_(long);
-
- template <template <typename...> class C, typename... Ts>
- using defer_ = decltype(detail::try_defer_<C, Ts...>(0));
-
- template <typename T, template <T...> class C, T... Is, template <T...> class D = C>
- id<D<Is...>> try_defer_i_(int);
- template <typename T, template <T...> class C, T... Is>
- nil_ try_defer_i_(long);
-
- template <typename T, template <T...> class C, T... Is>
- using defer_i_ = decltype(detail::try_defer_i_<T, C, Is...>(0));
- #endif // Concepts vs. MSVC vs. Other
-
- template <typename T>
- using _t_t = _t<_t<T>>;
- } // namespace detail
- /// \endcond
-
- ///////////////////////////////////////////////////////////////////////////////////////////
- // defer
- /// A wrapper that defers the instantiation of a template \p C with type parameters \p Ts in
- /// a \c lambda or \c let expression.
- ///
- /// In the code below, the lambda would ideally be written as
- /// `lambda<_a,_b,push_back<_a,_b>>`, however this fails since `push_back` expects its first
- /// argument to be a list, not a placeholder. Instead, we express it using \c defer as
- /// follows:
- ///
- /// \code
- /// template <typename L>
- /// using reverse = reverse_fold<L, list<>, lambda<_a, _b, defer<push_back, _a, _b>>>;
- /// \endcode
- ///
- /// \ingroup invocation
- template <template <typename...> class C, typename... Ts>
- struct defer : detail::defer_<C, Ts...>
- {
- };
-
- ///////////////////////////////////////////////////////////////////////////////////////////
- // defer_i
- /// A wrapper that defers the instantiation of a template \p C with integral constant
- /// parameters \p Is in a \c lambda or \c let expression.
- /// \sa `defer`
- /// \ingroup invocation
- template <typename T, template <T...> class C, T... Is>
- struct defer_i : detail::defer_i_<T, C, Is...>
- {
- };
-
- ///////////////////////////////////////////////////////////////////////////////////////////
- // defer_trait
- /// A wrapper that defers the instantiation of a trait \p C with type parameters \p Ts in a
- /// \c lambda or \c let expression.
- /// \sa `defer`
- /// \ingroup invocation
- template <template <typename...> class C, typename... Ts>
- using defer_trait = defer<detail::_t_t, detail::defer_<C, Ts...>>;
-
- ///////////////////////////////////////////////////////////////////////////////////////////
- // defer_trait_i
- /// A wrapper that defers the instantiation of a trait \p C with integral constant
- /// parameters \p Is in a \c lambda or \c let expression.
- /// \sa `defer_i`
- /// \ingroup invocation
- template <typename T, template <T...> class C, T... Is>
- using defer_trait_i = defer<detail::_t_t, detail::defer_i_<T, C, Is...>>;
-
- /// An alias that computes the size of the type \p T.
- /// \par Complexity
- /// \f$ O(1) \f$.
- /// \ingroup trait
- template <typename T>
- using sizeof_ = meta::size_t<sizeof(T)>;
-
- /// An alias that computes the alignment required for any instance of the type \p T.
- /// \par Complexity
- /// \f$ O(1) \f$.
- /// \ingroup trait
- template <typename T>
- using alignof_ = meta::size_t<alignof(T)>;
-
- namespace lazy
- {
- /// \sa `meta::sizeof_`
- /// \ingroup lazy_trait
- template <typename T>
- using sizeof_ = defer<sizeof_, T>;
-
- /// \sa `meta::alignof_`
- /// \ingroup lazy_trait
- template <typename T>
- using alignof_ = defer<alignof_, T>;
- } // namespace lazy
-
- #if META_CXX_VARIABLE_TEMPLATES
- /// is
- /// Test whether a type \p T is an instantiation of class
- /// template \p C.
- /// \ingroup trait
- template <typename T, template <typename...> class C>
- using is = bool_<is_v<T, C>>;
- #else
- /// is
- /// \cond
- namespace detail
- {
- template <typename, template <typename...> class>
- struct is_ : std::false_type
- {
- };
-
- template <typename... Ts, template <typename...> class C>
- struct is_<C<Ts...>, C> : std::true_type
- {
- };
- } // namespace detail
- /// \endcond
-
- /// Test whether a type \c T is an instantiation of class
- /// template \c C.
- /// \ingroup trait
- template <typename T, template <typename...> class C>
- using is = _t<detail::is_<T, C>>;
- #endif
-
- /// Compose the Invocables \p Fns in the parameter pack \p Ts.
- /// \ingroup composition
- template <META_TYPE_CONSTRAINT(invocable)... Fns>
- struct compose_
- {
- };
-
- template <META_TYPE_CONSTRAINT(invocable) Fn0>
- struct compose_<Fn0>
- {
- template <typename... Ts>
- using invoke = invoke<Fn0, Ts...>;
- };
-
- template <META_TYPE_CONSTRAINT(invocable) Fn0, META_TYPE_CONSTRAINT(invocable)... Fns>
- struct compose_<Fn0, Fns...>
- {
- template <typename... Ts>
- using invoke = invoke<Fn0, invoke<compose_<Fns...>, Ts...>>;
- };
-
- template <typename... Fns>
- using compose = compose_<Fns...>;
-
- namespace lazy
- {
- /// \sa 'meta::compose'
- /// \ingroup lazy_composition
- template <typename... Fns>
- using compose = defer<compose, Fns...>;
- } // namespace lazy
-
- /// Turn a template \p C into an invocable.
- /// \ingroup composition
- template <template <typename...> class C>
- struct quote
- {
- // Indirection through defer here needed to avoid Core issue 1430
- // https://wg21.link/cwg1430
- template <typename... Ts>
- using invoke = _t<defer<C, Ts...>>;
- };
-
- /// Turn a template \p C taking literals of type \p T into a
- /// invocable.
- /// \ingroup composition
- template <typename T, template <T...> class C>
- struct quote_i
- {
- // Indirection through defer_i here needed to avoid Core issue 1430
- // https://wg21.link/cwg1430
- template <META_TYPE_CONSTRAINT(integral)... Ts>
- using invoke = _t<defer_i<T, C, Ts::type::value...>>;
- };
-
- #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ == 4 && __GNUC_MINOR__ <= 8 && \
- !defined(META_DOXYGEN_INVOKED)
- template <template <typename...> class C>
- struct quote_trait
- {
- template <typename... Ts>
- using invoke = _t<invoke<quote<C>, Ts...>>;
- };
-
- template <typename T, template <T...> class C>
- struct quote_trait_i
- {
- template <typename... Ts>
- using invoke = _t<invoke<quote_i<T, C>, Ts...>>;
- };
- #else
- // clang-format off
- /// Turn a trait template \p C into an invocable.
- /// \code
- /// static_assert(std::is_same_v<invoke<quote_trait<std::add_const>, int>, int const>, "");
- /// \endcode
- /// \ingroup composition
- template <template <typename...> class C>
- using quote_trait = compose<quote<_t>, quote<C>>;
-
- /// Turn a trait template \p C taking literals of type \p T into an invocable.
- /// \ingroup composition
- template <typename T, template <T...> class C>
- using quote_trait_i = compose<quote<_t>, quote_i<T, C>>;
- // clang-format on
- #endif
-
- /// An invocable that partially applies the invocable
- /// \p Fn by binding the arguments \p Ts to the \e front of \p Fn.
- /// \ingroup composition
- template <META_TYPE_CONSTRAINT(invocable) Fn, typename... Ts>
- struct bind_front
- {
- template <typename... Us>
- using invoke = invoke<Fn, Ts..., Us...>;
- };
-
- /// An invocable that partially applies the invocable \p Fn by binding the
- /// arguments \p Us to the \e back of \p Fn.
- /// \ingroup composition
- template <META_TYPE_CONSTRAINT(invocable) Fn, typename... Us>
- struct bind_back
- {
- template <typename... Ts>
- using invoke = invoke<Fn, Ts..., Us...>;
- };
-
- namespace lazy
- {
- /// \sa 'meta::bind_front'
- /// \ingroup lazy_composition
- template <typename Fn, typename... Ts>
- using bind_front = defer<bind_front, Fn, Ts...>;
-
- /// \sa 'meta::bind_back'
- /// \ingroup lazy_composition
- template <typename Fn, typename... Ts>
- using bind_back = defer<bind_back, Fn, Ts...>;
- } // namespace lazy
-
- /// Extend meta with your own datatypes.
- namespace extension
- {
- /// A trait that unpacks the types in the type list \p L into the invocable
- /// \p Fn.
- /// \ingroup extension
- template <META_TYPE_CONSTRAINT(invocable) Fn, typename L>
- struct apply
- {
- };
-
- template <META_TYPE_CONSTRAINT(invocable) Fn, typename Ret, typename... Args>
- struct apply<Fn, Ret(Args...)> : lazy::invoke<Fn, Ret, Args...>
- {
- };
-
- template <META_TYPE_CONSTRAINT(invocable) Fn, template <typename...> class T,
- typename... Ts>
- struct apply<Fn, T<Ts...>> : lazy::invoke<Fn, Ts...>
- {
- };
-
- template <META_TYPE_CONSTRAINT(invocable) Fn, typename T, T... Is>
- struct apply<Fn, integer_sequence<T, Is...>>
- : lazy::invoke<Fn, std::integral_constant<T, Is>...>
- {
- };
- } // namespace extension
-
- /// Applies the invocable \p Fn using the types in the type list \p L as
- /// arguments.
- /// \ingroup invocation
- template <META_TYPE_CONSTRAINT(invocable) Fn, typename L>
- using apply = _t<extension::apply<Fn, L>>;
-
- namespace lazy
- {
- template <typename Fn, typename L>
- using apply = defer<apply, Fn, L>;
- }
-
- /// An invocable that takes a bunch of arguments, bundles them into a type
- /// list, and then calls the invocable \p Fn with the type list \p Q.
- /// \ingroup composition
- template <META_TYPE_CONSTRAINT(invocable) Fn,
- META_TYPE_CONSTRAINT(invocable) Q = quote<list>>
- using curry = compose<Fn, Q>;
-
- /// An invocable that takes a type list, unpacks the types, and then
- /// calls the invocable \p Fn with the types.
- /// \ingroup composition
- template <META_TYPE_CONSTRAINT(invocable) Fn>
- using uncurry = bind_front<quote<apply>, Fn>;
-
- namespace lazy
- {
- /// \sa 'meta::curry'
- /// \ingroup lazy_composition
- template <typename Fn, typename Q = quote<list>>
- using curry = defer<curry, Fn, Q>;
-
- /// \sa 'meta::uncurry'
- /// \ingroup lazy_composition
- template <typename Fn>
- using uncurry = defer<uncurry, Fn>;
- } // namespace lazy
-
- /// An invocable that reverses the order of the first two arguments.
- /// \ingroup composition
- template <META_TYPE_CONSTRAINT(invocable) Fn>
- struct flip
- {
- private:
- template <typename... Ts>
- struct impl
- {
- };
- template <typename A, typename B, typename... Ts>
- struct impl<A, B, Ts...> : lazy::invoke<Fn, B, A, Ts...>
- {
- };
-
- public:
- template <typename... Ts>
- using invoke = _t<impl<Ts...>>;
- };
-
- namespace lazy
- {
- /// \sa 'meta::flip'
- /// \ingroup lazy_composition
- template <typename Fn>
- using flip = defer<flip, Fn>;
- } // namespace lazy
-
- /// \cond
- namespace detail
- {
- template <typename...>
- struct on_
- {
- };
- template <typename Fn, typename... Gs>
- struct on_<Fn, Gs...>
- {
- template <typename... Ts>
- using invoke = invoke<Fn, invoke<compose<Gs...>, Ts>...>;
- };
- } // namespace detail
- /// \endcond
-
- /// Use as `on<Fn, Gs...>`. Creates an invocable that applies invocable \c Fn to the
- /// result of applying invocable `compose<Gs...>` to all the arguments.
- /// \ingroup composition
- template <META_TYPE_CONSTRAINT(invocable)... Fns>
- using on_ = detail::on_<Fns...>;
-
- template <typename... Fns>
- using on = on_<Fns...>;
-
- namespace lazy
- {
- /// \sa 'meta::on'
- /// \ingroup lazy_composition
- template <typename Fn, typename G>
- using on = defer<on, Fn, G>;
- } // namespace lazy
-
- ///////////////////////////////////////////////////////////////////////////////////////////
- // if_
- /// \cond
- namespace detail
- {
- #ifdef META_CONCEPT
- template <typename...>
- struct _if_
- {
- };
-
- template <integral If>
- struct _if_<If> : std::enable_if<_v<If>>
- {
- };
-
- template <integral If, typename Then>
- struct _if_<If, Then> : std::enable_if<_v<If>, Then>
- {
- };
-
- template <integral If, typename Then, typename Else>
- struct _if_<If, Then, Else> : std::conditional<_v<If>, Then, Else>
- {
- };
- #elif defined(__clang__)
- // Clang is faster with this implementation
- template <typename, typename = bool>
- struct _if_
- {
- };
-
- template <typename If>
- struct _if_<list<If>, decltype(bool(If::type::value))> : std::enable_if<If::type::value>
- {
- };
-
- template <typename If, typename Then>
- struct _if_<list<If, Then>, decltype(bool(If::type::value))>
- : std::enable_if<If::type::value, Then>
- {
- };
-
- template <typename If, typename Then, typename Else>
- struct _if_<list<If, Then, Else>, decltype(bool(If::type::value))>
- : std::conditional<If::type::value, Then, Else>
- {
- };
- #else
- // GCC seems to prefer this implementation
- template <typename, typename = std::true_type>
- struct _if_
- {
- };
-
- template <typename If>
- struct _if_<list<If>, bool_<If::type::value>>
- {
- using type = void;
- };
-
- template <typename If, typename Then>
- struct _if_<list<If, Then>, bool_<If::type::value>>
- {
- using type = Then;
- };
-
- template <typename If, typename Then, typename Else>
- struct _if_<list<If, Then, Else>, bool_<If::type::value>>
- {
- using type = Then;
- };
-
- template <typename If, typename Then, typename Else>
- struct _if_<list<If, Then, Else>, bool_<!If::type::value>>
- {
- using type = Else;
- };
- #endif
- } // namespace detail
- /// \endcond
-
- /// Select one type or another depending on a compile-time Boolean.
- /// \ingroup logical
- #ifdef META_CONCEPT
- template <typename... Args>
- using if_ = _t<detail::_if_<Args...>>;
-
- /// Select one type or another depending on a compile-time Boolean.
- /// \ingroup logical
- template <bool If, typename... Args>
- using if_c = _t<detail::_if_<bool_<If>, Args...>>;
- #else
- template <typename... Args>
- using if_ = _t<detail::_if_<list<Args...>>>;
-
- template <bool If, typename... Args>
- using if_c = _t<detail::_if_<list<bool_<If>, Args...>>>;
- #endif
-
- namespace lazy
- {
- /// \sa 'meta::if_'
- /// \ingroup lazy_logical
- template <typename... Args>
- using if_ = defer<if_, Args...>;
-
- /// \sa 'meta::if_c'
- /// \ingroup lazy_logical
- template <bool If, typename... Args>
- using if_c = if_<bool_<If>, Args...>;
- } // namespace lazy
-
- /// \cond
- namespace detail
- {
- #ifdef META_CONCEPT
- template <typename...>
- struct _and_
- {
- };
-
- template <>
- struct _and_<> : std::true_type
- {
- };
-
- template <integral B, typename... Bs>
- requires (bool(B::type::value)) struct _and_<B, Bs...> : _and_<Bs...>
- {
- };
-
- template <integral B, typename... Bs>
- requires (!bool(B::type::value)) struct _and_<B, Bs...> : std::false_type
- {
- };
-
- template <typename...>
- struct _or_
- {
- };
-
- template <>
- struct _or_<> : std::false_type
- {
- };
-
- template <integral B, typename... Bs>
- requires (bool(B::type::value)) struct _or_<B, Bs...> : std::true_type
- {
- };
-
- template <integral B, typename... Bs>
- requires (!bool(B::type::value)) struct _or_<B, Bs...> : _or_<Bs...>
- {
- };
- #else
- template <bool>
- struct _and_
- {
- template <typename...>
- using invoke = std::true_type;
- };
-
- template <>
- struct _and_<false>
- {
- template <typename B, typename... Bs>
- using invoke = invoke<
- if_c<!B::type::value, id<std::false_type>, _and_<0 == sizeof...(Bs)>>,
- Bs...>;
- };
-
- template <bool>
- struct _or_
- {
- template <typename = void>
- using invoke = std::false_type;
- };
-
- template <>
- struct _or_<false>
- {
- template <typename B, typename... Bs>
- using invoke = invoke<
- if_c<B::type::value, id<std::true_type>, _or_<0 == sizeof...(Bs)>>,
- Bs...>;
- };
- #endif
- } // namespace detail
- /// \endcond
-
- /// Logically negate the Boolean parameter
- /// \ingroup logical
- template <bool B>
- using not_c = bool_<!B>;
-
- /// Logically negate the integral constant-wrapped Boolean parameter.
- /// \ingroup logical
- template <META_TYPE_CONSTRAINT(integral) B>
- using not_ = not_c<B::type::value>;
-
- #if META_CXX_FOLD_EXPRESSIONS && !defined(META_WORKAROUND_GCC_UNKNOWN1)
- template <bool... Bs>
- META_INLINE_VAR constexpr bool and_v = (true && ... && Bs);
-
- /// Logically AND together all the Boolean parameters
- /// \ingroup logical
- template <bool... Bs>
- #if defined(META_WORKAROUND_MSVC_756112) || defined(META_WORKAROUND_GCC_86356)
- using and_c = bool_<and_v<Bs...>>;
- #else
- using and_c = bool_<(true && ... && Bs)>;
- #endif
- #else
- #if defined(META_WORKAROUND_GCC_66405)
- template <bool... Bs>
- using and_c = meta::bool_<
- META_IS_SAME(integer_sequence<bool, true, Bs...>,
- integer_sequence<bool, Bs..., true>)>;
- #else
- template <bool... Bs>
- struct and_c
- : meta::bool_<
- META_IS_SAME(integer_sequence<bool, Bs...>,
- integer_sequence<bool, (Bs || true)...>)>
- {};
- #endif
- #if META_CXX_VARIABLE_TEMPLATES
- template <bool... Bs>
- META_INLINE_VAR constexpr bool and_v =
- META_IS_SAME(integer_sequence<bool, Bs...>,
- integer_sequence<bool, (Bs || true)...>);
- #endif
- #endif
-
- /// Logically AND together all the integral constant-wrapped Boolean
- /// parameters, \e without short-circuiting.
- /// \ingroup logical
- template <META_TYPE_CONSTRAINT(integral)... Bs>
- using strict_and_ = and_c<Bs::type::value...>;
-
- template <typename... Bs>
- using strict_and = strict_and_<Bs...>;
-
- /// Logically AND together all the integral constant-wrapped Boolean
- /// parameters, \e with short-circuiting.
- /// \ingroup logical
- template <typename... Bs>
- #ifdef META_CONCEPT
- using and_ = _t<detail::_and_<Bs...>>;
- #else
- // Make a trip through defer<> to avoid CWG1430
- // https://wg21.link/cwg1430
- using and_ = _t<defer<detail::_and_<0 == sizeof...(Bs)>::template invoke, Bs...>>;
- #endif
-
- /// Logically OR together all the Boolean parameters
- /// \ingroup logical
- #if META_CXX_FOLD_EXPRESSIONS && !defined(META_WORKAROUND_GCC_UNKNOWN1)
- template <bool... Bs>
- META_INLINE_VAR constexpr bool or_v = (false || ... || Bs);
-
- template <bool... Bs>
- #if defined(META_WORKAROUND_MSVC_756112) || defined(META_WORKAROUND_GCC_86356)
- using or_c = bool_<or_v<Bs...>>;
- #else
- using or_c = bool_<(false || ... || Bs)>;
- #endif
- #else
- template <bool... Bs>
- struct or_c
- : meta::bool_<
- !META_IS_SAME(integer_sequence<bool, Bs...>,
- integer_sequence<bool, (Bs && false)...>)>
- {};
- #if META_CXX_VARIABLE_TEMPLATES
- template <bool... Bs>
- META_INLINE_VAR constexpr bool or_v =
- !META_IS_SAME(integer_sequence<bool, Bs...>,
- integer_sequence<bool, (Bs && false)...>);
- #endif
- #endif
-
- /// Logically OR together all the integral constant-wrapped Boolean
- /// parameters, \e without short-circuiting.
- /// \ingroup logical
- template <META_TYPE_CONSTRAINT(integral)... Bs>
- using strict_or_ = or_c<Bs::type::value...>;
-
- template <typename... Bs>
- using strict_or = strict_or_<Bs...>;
-
- /// Logically OR together all the integral constant-wrapped Boolean
- /// parameters, \e with short-circuiting.
- /// \ingroup logical
- template <typename... Bs>
- #ifdef META_CONCEPT
- using or_ = _t<detail::_or_<Bs...>>;
- #else
- // Make a trip through defer<> to avoid CWG1430
- // https://wg21.link/cwg1430
- using or_ = _t<defer<detail::_or_<0 == sizeof...(Bs)>::template invoke, Bs...>>;
- #endif
-
- namespace lazy
- {
- /// \sa 'meta::and_'
- /// \ingroup lazy_logical
- template <typename... Bs>
- using and_ = defer<and_, Bs...>;
-
- /// \sa 'meta::or_'
- /// \ingroup lazy_logical
- template <typename... Bs>
- using or_ = defer<or_, Bs...>;
-
- /// \sa 'meta::not_'
- /// \ingroup lazy_logical
- template <typename B>
- using not_ = defer<not_, B>;
-
- /// \sa 'meta::strict_and'
- /// \ingroup lazy_logical
- template <typename... Bs>
- using strict_and = defer<strict_and, Bs...>;
-
- /// \sa 'meta::strict_or'
- /// \ingroup lazy_logical
- template <typename... Bs>
- using strict_or = defer<strict_or, Bs...>;
- } // namespace lazy
-
- ///////////////////////////////////////////////////////////////////////////////////////////
- // fold
- /// \cond
- namespace detail
- {
- template <typename, typename, typename>
- struct fold_
- {
- };
-
- template <typename Fn, typename T0, typename T1, typename T2, typename T3, typename T4,
- typename T5, typename T6, typename T7, typename T8, typename T9>
- struct compose10_
- {
- template <typename X, typename Y>
- using F = invoke<Fn, X, Y>;
-
- template <typename S>
- using invoke =
- F<F<F<F<F<F<F<F<F<F<_t<S>, T0>, T1>, T2>, T3>, T4>, T5>, T6>, T7>, T8>, T9>;
- };
-
- #ifdef META_CONCEPT
- template <typename Fn>
- struct compose_
- {
- template <typename X, typename Y>
- using F = invoke<Fn, X, Y>;
-
- template <typename T0, typename T1, typename T2, typename T3, typename T4,
- typename T5, typename T6, typename T7, typename T8, typename T9,
- typename State>
- using invoke =
- F<F<F<F<F<F<F<F<F<F<State, T0>, T1>, T2>, T3>, T4>, T5>, T6>, T7>, T8>, T9>;
- };
-
- template <typename State, typename Fn>
- struct fold_<list<>, State, Fn>
- {
- using type = State;
- };
-
- template <typename Head, typename... Tail, typename State, typename Fn>
- requires valid<invoke, Fn, State, Head>
- struct fold_<list<Head, Tail...>, State, Fn>
- : fold_<list<Tail...>, invoke<Fn, State, Head>, Fn>
- {
- };
-
- template <typename T0, typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename... Tail,
- typename State, typename Fn>
- requires valid<invoke, compose_<Fn>, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, State>
- struct fold_<list<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, Tail...>, State, Fn>
- : fold_<list<Tail...>,
- invoke<compose_<Fn>, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, State>, Fn>
- {
- };
- #else // ^^^ Concepts / no Concepts vvv
- template <typename Fn, typename T0>
- struct compose1_
- {
- template <typename X>
- using invoke = invoke<Fn, _t<X>, T0>;
- };
-
- template <typename State, typename Fn>
- struct fold_<list<>, State, Fn> : State
- {
- };
-
- template <typename Head, typename... Tail, typename State, typename Fn>
- struct fold_<list<Head, Tail...>, State, Fn>
- : fold_<list<Tail...>, lazy::invoke<compose1_<Fn, Head>, State>, Fn>
- {
- };
-
- template <typename T0, typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename... Tail,
- typename State, typename Fn>
- struct fold_<list<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, Tail...>, State, Fn>
- : fold_<list<Tail...>,
- lazy::invoke<compose10_<Fn, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>, State>, Fn>
- {
- };
- #endif // META_CONCEPT
- } // namespace detail
- /// \endcond
-
- /// Return a new \c meta::list constructed by doing a left fold of the list \p L using
- /// binary invocable \p Fn and initial state \p State. That is, the \c State_N for
- /// the list element \c A_N is computed by `Fn(State_N-1, A_N) -> State_N`.
- /// \par Complexity
- /// \f$ O(N) \f$.
- /// \ingroup transformation
- template <META_TYPE_CONSTRAINT(list_like) L, typename State, META_TYPE_CONSTRAINT(invocable) Fn>
- #ifdef META_CONCEPT
- using fold = _t<detail::fold_<L, State, Fn>>;
- #else
- using fold = _t<detail::fold_<L, id<State>, Fn>>;
- #endif
-
- /// An alias for `meta::fold`.
- /// \par Complexity
- /// \f$ O(N) \f$.
- /// \ingroup transformation
- template <META_TYPE_CONSTRAINT(list_like) L, typename State, META_TYPE_CONSTRAINT(invocable) Fn>
- using accumulate = fold<L, State, Fn>;
-
- namespace lazy
- {
- /// \sa 'meta::foldl'
- /// \ingroup lazy_transformation
- template <typename L, typename State, typename Fn>
- using fold = defer<fold, L, State, Fn>;
-
- /// \sa 'meta::accumulate'
- /// \ingroup lazy_transformation
- template <typename L, typename State, typename Fn>
- using accumulate = defer<accumulate, L, State, Fn>;
- } // namespace lazy
-
- ///////////////////////////////////////////////////////////////////////////////////////////
- // reverse_fold
- /// \cond
- namespace detail
- {
- template <typename, typename, typename>
- struct reverse_fold_
- {
- };
-
- template <typename State, typename Fn>
- struct reverse_fold_<list<>, State, Fn>
- {
- using type = State;
- };
-
- #ifdef META_CONCEPT
- template <typename Head, typename... L, typename State, typename Fn>
- requires trait<reverse_fold_<list<L...>, State, Fn>> struct reverse_fold_<
- list<Head, L...>, State, Fn>
- : lazy::invoke<Fn, _t<reverse_fold_<list<L...>, State, Fn>>, Head>
- {
- };
- #else
- template <typename Head, typename... Tail, typename State, typename Fn>
- struct reverse_fold_<list<Head, Tail...>, State, Fn>
- : lazy::invoke<compose1_<Fn, Head>, reverse_fold_<list<Tail...>, State, Fn>>
- {
- };
- #endif
-
- template <typename T0, typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename... Tail,
- typename State, typename Fn>
- struct reverse_fold_<list<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, Tail...>, State, Fn>
- : lazy::invoke<compose10_<Fn, T9, T8, T7, T6, T5, T4, T3, T2, T1, T0>,
- reverse_fold_<list<Tail...>, State, Fn>>
- {
- };
- } // namespace detail
- /// \endcond
-
- /// Return a new \c meta::list constructed by doing a right fold of the list \p L using
- /// binary invocable \p Fn and initial state \p State. That is, the \c State_N for the list
- /// element \c A_N is computed by `Fn(A_N, State_N+1) -> State_N`.
- /// \par Complexity
- /// \f$ O(N) \f$.
- /// \ingroup transformation
- template <META_TYPE_CONSTRAINT(list_like) L, typename State, META_TYPE_CONSTRAINT(invocable) Fn>
- using reverse_fold = _t<detail::reverse_fold_<L, State, Fn>>;
-
- namespace lazy
- {
- /// \sa 'meta::foldr'
- /// \ingroup lazy_transformation
- template <typename L, typename State, typename Fn>
- using reverse_fold = defer<reverse_fold, L, State, Fn>;
- } // namespace lazy
-
- ///////////////////////////////////////////////////////////////////////////////////////////
- // npos
- /// A special value used to indicate no matches. It equals the maximum
- /// value representable by std::size_t.
- /// \ingroup list
- using npos = meta::size_t<std::size_t(-1)>;
-
- ///////////////////////////////////////////////////////////////////////////////////////////
- // list
- /// A list of types.
- /// \ingroup list
- template <typename... Ts>
- struct list
- {
- using type = list;
- /// \return `sizeof...(Ts)`
- static constexpr std::size_t size() noexcept { return sizeof...(Ts); }
- };
-
- ///////////////////////////////////////////////////////////////////////////////////////////
- // size
- /// An integral constant wrapper that is the size of the \c meta::list
- /// \p L.
- /// \ingroup list
- template <META_TYPE_CONSTRAINT(list_like) L>
- using size = meta::size_t<L::size()>;
-
- namespace lazy
- {
- /// \sa 'meta::size'
- /// \ingroup lazy_list
- template <typename L>
- using size = defer<size, L>;
- } // namespace lazy
-
- ///////////////////////////////////////////////////////////////////////////////////////////
- // concat
- /// \cond
- namespace detail
- {
- template <typename... Lists>
- struct concat_
- {
- };
-
- template <>
- struct concat_<>
- {
- using type = list<>;
- };
-
- template <typename... L1>
- struct concat_<list<L1...>>
- {
- using type = list<L1...>;
- };
-
- template <typename... L1, typename... L2>
- struct concat_<list<L1...>, list<L2...>>
- {
- using type = list<L1..., L2...>;
- };
-
- template <typename... L1, typename... L2, typename... L3>
- struct concat_<list<L1...>, list<L2...>, list<L3...>>
- {
- using type = list<L1..., L2..., L3...>;
- };
-
- template <typename... L1, typename... L2, typename... L3, typename... Rest>
- struct concat_<list<L1...>, list<L2...>, list<L3...>, Rest...>
- : concat_<list<L1..., L2..., L3...>, Rest...>
- {
- };
-
- template <typename... L1, typename... L2, typename... L3, typename... L4,
- typename... L5, typename... L6, typename... L7, typename... L8,
- typename... L9, typename... L10, typename... Rest>
- struct concat_<list<L1...>, list<L2...>, list<L3...>, list<L4...>, list<L5...>,
- list<L6...>, list<L7...>, list<L8...>, list<L9...>, list<L10...>,
- Rest...>
- : concat_<list<L1..., L2..., L3..., L4..., L5..., L6..., L7..., L8..., L9..., L10...>,
- Rest...>
- {
- };
- } // namespace detail
- /// \endcond
-
- /// Concatenates several lists into a single list.
- /// \pre The parameters must all be instantiations of \c meta::list.
- /// \par Complexity
- /// \f$ O(L) \f$ where \f$ L \f$ is the number of lists in the list of lists.
- /// \ingroup transformation
- template <META_TYPE_CONSTRAINT(list_like)... Ls>
- using concat_ = _t<detail::concat_<Ls...>>;
-
- template <typename... Lists>
- using concat = concat_<Lists...>;
-
- namespace lazy
- {
- /// \sa 'meta::concat'
- /// \ingroup lazy_transformation
- template <typename... Lists>
- using concat = defer<concat, Lists...>;
- } // namespace lazy
-
- /// Joins a list of lists into a single list.
- /// \pre The parameter must be an instantiation of \c meta::list\<T...\>
- /// where each \c T is itself an instantiation of \c meta::list.
- /// \par Complexity
- /// \f$ O(L) \f$ where \f$ L \f$ is the number of lists in the list of
- /// lists.
- /// \ingroup transformation
- template <META_TYPE_CONSTRAINT(list_like) ListOfLists>
- using join = apply<quote<concat>, ListOfLists>;
-
- namespace lazy
- {
- /// \sa 'meta::join'
- /// \ingroup lazy_transformation
- template <typename ListOfLists>
- using join = defer<join, ListOfLists>;
- } // namespace lazy
-
- ///////////////////////////////////////////////////////////////////////////////////////////
- // transform
- /// \cond
- namespace detail
- {
- #ifdef META_CONCEPT
- template <typename... Args>
- struct transform_
- {
- };
-
- template <typename... Ts, invocable Fn>
- requires and_v<valid<invoke, Fn, Ts>...>
- struct transform_<list<Ts...>, Fn>
- {
- using type = list<invoke<Fn, Ts>...>;
- };
-
- template <typename... Ts, typename... Us, invocable Fn>
- requires and_v<valid<invoke, Fn, Ts, Us>...>
- struct transform_<list<Ts...>, list<Us...>, Fn>
- {
- using type = list<invoke<Fn, Ts, Us>...>;
- };
- #else
- template <typename, typename = void>
- struct transform_
- {
- };
-
- template <typename... Ts, typename Fn>
- struct transform_<list<list<Ts...>, Fn>, void_<invoke<Fn, Ts>...>>
- {
- using type = list<invoke<Fn, Ts>...>;
- };
-
- template <typename... Ts0, typename... Ts1, typename Fn>
- struct transform_<list<list<Ts0...>, list<Ts1...>, Fn>,
- void_<invoke<Fn, Ts0, Ts1>...>>
- {
- using type = list<invoke<Fn, Ts0, Ts1>...>;
- };
- #endif
- } // namespace detail
- /// \endcond
-
- /// Return a new \c meta::list constructed by transforming all the
- /// elements in \p L with the unary invocable \p Fn. \c transform can
- /// also be called with two lists of the same length and a binary
- /// invocable, in which case it returns a new list constructed with the
- /// results of calling \c Fn with each element in the lists, pairwise.
- /// \par Complexity
- /// \f$ O(N) \f$.
- /// \ingroup transformation
- #ifdef META_CONCEPT
- template <typename... Args>
- using transform = _t<detail::transform_<Args...>>;
- #else
- template <typename... Args>
- using transform = _t<detail::transform_<list<Args...>>>;
- #endif
-
- namespace lazy
- {
- /// \sa 'meta::transform'
- /// \ingroup lazy_transformation
- template <typename... Args>
- using transform = defer<transform, Args...>;
- } // namespace lazy
-
- ///////////////////////////////////////////////////////////////////////////////////////////
- // repeat_n
- /// \cond
- namespace detail
- {
- template <typename T, std::size_t>
- using first_ = T;
-
- template <typename T, typename Ints>
- struct repeat_n_c_
- {
- };
-
- template <typename T, std::size_t... Is>
- struct repeat_n_c_<T, index_sequence<Is...>>
- {
- using type = list<first_<T, Is>...>;
- };
- } // namespace detail
- /// \endcond
-
- /// Generate `list<T,T,T...T>` of size \p N arguments.
- /// \par Complexity
- /// \f$ O(log N) \f$.
- /// \ingroup list
- template <std::size_t N, typename T = void>
- using repeat_n_c = _t<detail::repeat_n_c_<T, make_index_sequence<N>>>;
-
- /// Generate `list<T,T,T...T>` of size \p N arguments.
- /// \par Complexity
- /// \f$ O(log N) \f$.
- /// \ingroup list
- template <META_TYPE_CONSTRAINT(integral) N, typename T = void>
- using repeat_n = repeat_n_c<N::type::value, T>;
-
- namespace lazy
- {
- /// \sa 'meta::repeat_n'
- /// \ingroup lazy_list
- template <typename N, typename T = void>
- using repeat_n = defer<repeat_n, N, T>;
-
- /// \sa 'meta::repeat_n_c'
- /// \ingroup lazy_list
- template <std::size_t N, typename T = void>
- using repeat_n_c = defer<repeat_n, meta::size_t<N>, T>;
- } // namespace lazy
-
- ///////////////////////////////////////////////////////////////////////////////////////////
- // at
- /// \cond
- namespace detail
- {
- #if META_HAS_TYPE_PACK_ELEMENT && !defined(META_DOXYGEN_INVOKED)
- template <typename L, std::size_t N, typename = void>
- struct at_
- {
- };
-
- template <typename... Ts, std::size_t N>
- struct at_<list<Ts...>, N, void_<__type_pack_element<N, Ts...>>>
- {
- using type = __type_pack_element<N, Ts...>;
- };
- #else
- template <typename VoidPtrs>
- struct at_impl_;
-
- template <typename... VoidPtrs>
- struct at_impl_<list<VoidPtrs...>>
- {
- static nil_ eval(...);
-
- template <typename T, typename... Us>
- static T eval(VoidPtrs..., T *, Us *...);
- };
-
- template <typename L, std::size_t N>
- struct at_
- {
- };
-
- template <typename... Ts, std::size_t N>
- struct at_<list<Ts...>, N>
- : decltype(at_impl_<repeat_n_c<N, void *>>::eval(static_cast<id<Ts> *>(nullptr)...))
- {
- };
- #endif // META_HAS_TYPE_PACK_ELEMENT
- } // namespace detail
- /// \endcond
-
- /// Return the \p N th element in the \c meta::list \p L.
- /// \par Complexity
- /// Amortized \f$ O(1) \f$.
- /// \ingroup list
- template <META_TYPE_CONSTRAINT(list_like) L, std::size_t N>
- using at_c = _t<detail::at_<L, N>>;
-
- /// Return the \p N th element in the \c meta::list \p L.
- /// \par Complexity
- /// Amortized \f$ O(1) \f$.
- /// \ingroup list
- template <META_TYPE_CONSTRAINT(list_like) L, META_TYPE_CONSTRAINT(integral) N>
- using at = at_c<L, N::type::value>;
-
- namespace lazy
- {
- /// \sa 'meta::at'
- /// \ingroup lazy_list
- template <typename L, typename N>
- using at = defer<at, L, N>;
- } // namespace lazy
-
- ///////////////////////////////////////////////////////////////////////////////////////////
- // drop
- /// \cond
- namespace detail
- {
- ///////////////////////////////////////////////////////////////////////////////////////
- /// drop_impl_
- template <typename VoidPtrs>
- struct drop_impl_
- {
- static nil_ eval(...);
- };
-
- template <typename... VoidPtrs>
- struct drop_impl_<list<VoidPtrs...>>
- {
- static nil_ eval(...);
-
- template <typename... Ts>
- static id<list<Ts...>> eval(VoidPtrs..., id<Ts> *...);
- };
-
- template <>
- struct drop_impl_<list<>>
- {
- template <typename... Ts>
- static id<list<Ts...>> eval(id<Ts> *...);
- };
-
- template <typename L, std::size_t N>
- struct drop_
- {
- };
-
- template <typename... Ts, std::size_t N>
- struct drop_<list<Ts...>, N>
- #if META_CXX_VARIABLE_TEMPLATES
- : decltype(drop_impl_<repeat_n_c<N, void *>>::eval(detail::nullptr_v<id<Ts>>...))
- #else
- : decltype(drop_impl_<repeat_n_c<N, void *>>::eval(detail::_nullptr_v<id<Ts>>()...))
- #endif
- {
- };
- } // namespace detail
- /// \endcond
-
- /// Return a new \c meta::list by removing the first \p N elements from \p L.
- /// \par Complexity
- /// \f$ O(1) \f$.
- /// \ingroup transformation
- template <META_TYPE_CONSTRAINT(list_like) L, std::size_t N>
- using drop_c = _t<detail::drop_<L, N>>;
-
- /// Return a new \c meta::list by removing the first \p N elements from \p L.
- /// \par Complexity
- /// \f$ O(1) \f$.
- /// \ingroup transformation
- template <META_TYPE_CONSTRAINT(list_like) L, META_TYPE_CONSTRAINT(integral) N>
- using drop = drop_c<L, N::type::value>;
-
- namespace lazy
- {
- /// \sa 'meta::drop'
- /// \ingroup lazy_transformation
- template <typename L, typename N>
- using drop = defer<drop, L, N>;
- } // namespace lazy
-
- ///////////////////////////////////////////////////////////////////////////////////////////
- // front
- /// \cond
- namespace detail
- {
- template <typename L>
- struct front_
- {
- };
-
- template <typename Head, typename... Tail>
- struct front_<list<Head, Tail...>>
- {
- using type = Head;
- };
- } // namespace detail
- /// \endcond
-
- /// Return the first element in \c meta::list \p L.
- /// \par Complexity
- /// \f$ O(1) \f$.
- /// \ingroup list
- template <META_TYPE_CONSTRAINT(list_like) L>
- using front = _t<detail::front_<L>>;
-
- namespace lazy
- {
- /// \sa 'meta::front'
- /// \ingroup lazy_list
- template <typename L>
- using front = defer<front, L>;
- } // namespace lazy
-
- ///////////////////////////////////////////////////////////////////////////////////////////
- // back
- /// \cond
- namespace detail
- {
- template <typename L>
- struct back_
- {
- };
-
- template <typename Head, typename... Tail>
- struct back_<list<Head, Tail...>>
- {
- using type = at_c<list<Head, Tail...>, sizeof...(Tail)>;
- };
- } // namespace detail
- /// \endcond
-
- /// Return the last element in \c meta::list \p L.
- /// \par Complexity
- /// Amortized \f$ O(1) \f$.
- /// \ingroup list
- template <META_TYPE_CONSTRAINT(list_like) L>
- using back = _t<detail::back_<L>>;
-
- namespace lazy
- {
- /// \sa 'meta::back'
- /// \ingroup lazy_list
- template <typename L>
- using back = defer<back, L>;
- } // namespace lazy
-
- ///////////////////////////////////////////////////////////////////////////////////////////
- // push_front
- /// Return a new \c meta::list by adding the element \c T to the front of \p L.
- /// \par Complexity
- /// \f$ O(1) \f$.
- /// \ingroup transformation
- template <META_TYPE_CONSTRAINT(list_like) L, typename... Ts>
- using push_front = apply<bind_front<quote<list>, Ts...>, L>;
-
- namespace lazy
- {
- /// \sa 'meta::push_front'
- /// \ingroup lazy_transformation
- template <typename... Ts>
- using push_front = defer<push_front, Ts...>;
- } // namespace lazy
-
- ///////////////////////////////////////////////////////////////////////////////////////////
- // pop_front
- /// \cond
- namespace detail
- {
- template <typename L>
- struct pop_front_
- {
- };
-
- template <typename Head, typename... L>
- struct pop_front_<list<Head, L...>>
- {
- using type = list<L...>;
- };
- } // namespace detail
- /// \endcond
-
- /// Return a new \c meta::list by removing the first element from the
- /// front of \p L.
- /// \par Complexity
- /// \f$ O(1) \f$.
- /// \ingroup transformation
- template <META_TYPE_CONSTRAINT(list_like) L>
- using pop_front = _t<detail::pop_front_<L>>;
-
- namespace lazy
- {
- /// \sa 'meta::pop_front'
- /// \ingroup lazy_transformation
- template <typename L>
- using pop_front = defer<pop_front, L>;
- } // namespace lazy
-
- ///////////////////////////////////////////////////////////////////////////////////////////
- // push_back
- /// Return a new \c meta::list by adding the element \c T to the back of \p L.
- /// \par Complexity
- /// \f$ O(1) \f$.
- /// \note \c pop_back not provided because it cannot be made to meet the
- /// complexity guarantees one would expect.
- /// \ingroup transformation
- template <META_TYPE_CONSTRAINT(list_like) L, typename... Ts>
- using push_back = apply<bind_back<quote<list>, Ts...>, L>;
-
- namespace lazy
- {
- /// \sa 'meta::push_back'
- /// \ingroup lazy_transformation
- template <typename... Ts>
- using push_back = defer<push_back, Ts...>;
- } // namespace lazy
-
- /// \cond
- namespace detail
- {
- template <typename T, typename U>
- using min_ = if_<less<U, T>, U, T>;
-
- template <typename T, typename U>
- using max_ = if_<less<U, T>, T, U>;
- } // namespace detail
- /// \endcond
-
- /// An integral constant wrapper around the minimum of `Ts::type::value...`
- /// \ingroup math
- template <META_TYPE_CONSTRAINT(integral)... Ts>
- using min_ = fold<pop_front<list<Ts...>>, front<list<Ts...>>, quote<detail::min_>>;
-
- template <typename... Ts>
- using min = min_<Ts...>;
-
- /// An integral constant wrapper around the maximum of `Ts::type::value...`
- /// \ingroup math
- template <META_TYPE_CONSTRAINT(integral)... Ts>
- using max_ = fold<pop_front<list<Ts...>>, front<list<Ts...>>, quote<detail::max_>>;
-
- template <typename... Ts>
- using max = max_<Ts...>;
-
- namespace lazy
- {
- /// \sa 'meta::min'
- /// \ingroup lazy_math
- template <typename... Ts>
- using min = defer<min, Ts...>;
-
- /// \sa 'meta::max'
- /// \ingroup lazy_math
- template <typename... Ts>
- using max = defer<max, Ts...>;
- } // namespace lazy
-
- ///////////////////////////////////////////////////////////////////////////////////////////
- // empty
- /// An Boolean integral constant wrapper around \c true if \p L is an
- /// empty type list; \c false, otherwise.
- /// \par Complexity
- /// \f$ O(1) \f$.
- /// \ingroup list
- template <META_TYPE_CONSTRAINT(list_like) L>
- using empty = bool_<0 == size<L>::type::value>;
-
- namespace lazy
- {
- /// \sa 'meta::empty'
- /// \ingroup lazy_list
- template <typename L>
- using empty = defer<empty, L>;
- } // namespace lazy
-
- ///////////////////////////////////////////////////////////////////////////////////////////
- // pair
- /// A list with exactly two elements
- /// \ingroup list
- template <typename F, typename S>
- using pair = list<F, S>;
-
- /// Retrieve the first element of the \c pair \p Pair
- /// \ingroup list
- template <typename Pair>
- using first = front<Pair>;
-
- /// Retrieve the first element of the \c pair \p Pair
- /// \ingroup list
- template <typename Pair>
- using second = front<pop_front<Pair>>;
-
- namespace lazy
- {
- /// \sa 'meta::first'
- /// \ingroup lazy_list
- template <typename Pair>
- using first = defer<first, Pair>;
-
- /// \sa 'meta::second'
- /// \ingroup lazy_list
- template <typename Pair>
- using second = defer<second, Pair>;
- } // namespace lazy
-
- ///////////////////////////////////////////////////////////////////////////////////////////
- // find_index
- /// \cond
- namespace detail
- {
- // With thanks to Peter Dimov:
- constexpr std::size_t find_index_i_(bool const *const first, bool const *const last,
- std::size_t N = 0)
- {
- return first == last ? npos::value
- : *first ? N : find_index_i_(first + 1, last, N + 1);
- }
-
- template <typename L, typename T>
- struct find_index_
- {
- };
-
- template <typename V>
- struct find_index_<list<>, V>
- {
- using type = npos;
- };
-
- template <typename... T, typename V>
- struct find_index_<list<T...>, V>
- {
- #ifdef META_WORKAROUND_LLVM_28385
- static constexpr bool s_v[sizeof...(T)] = {META_IS_SAME(T, V)...};
- #else
- static constexpr bool s_v[] = {META_IS_SAME(T, V)...};
- #endif
- using type = size_t<find_index_i_(s_v, s_v + sizeof...(T))>;
- };
- } // namespace detail
- /// \endcond
-
- /// Finds the index of the first occurrence of the type \p T within the list \p L.
- /// Returns `#meta::npos` if the type \p T was not found.
- /// \par Complexity
- /// \f$ O(N) \f$.
- /// \ingroup query
- /// \sa `meta::npos`
- template <META_TYPE_CONSTRAINT(list_like) L, typename T>
- using find_index = _t<detail::find_index_<L, T>>;
-
- namespace lazy
- {
- /// \sa 'meta::find_index'
- /// \ingroup lazy_query
- template <typename L, typename T>
- using find_index = defer<find_index, L, T>;
- } // namespace lazy
-
- ///////////////////////////////////////////////////////////////////////////////////////////
- // reverse_find_index
- /// \cond
- namespace detail
- {
- // With thanks to Peter Dimov:
- constexpr std::size_t reverse_find_index_i_(bool const *const first,
- bool const *const last, std::size_t N)
- {
- return first == last
- ? npos::value
- : *(last - 1) ? N - 1 : reverse_find_index_i_(first, last - 1, N - 1);
- }
-
- template <typename L, typename T>
- struct reverse_find_index_
- {
- };
-
- template <typename V>
- struct reverse_find_index_<list<>, V>
- {
- using type = npos;
- };
-
- template <typename... T, typename V>
- struct reverse_find_index_<list<T...>, V>
- {
- #ifdef META_WORKAROUND_LLVM_28385
- static constexpr bool s_v[sizeof...(T)] = {META_IS_SAME(T, V)...};
- #else
- static constexpr bool s_v[] = {META_IS_SAME(T, V)...};
- #endif
- using type = size_t<reverse_find_index_i_(s_v, s_v + sizeof...(T), sizeof...(T))>;
- };
- } // namespace detail
- /// \endcond
-
- /// Finds the index of the last occurrence of the type \p T within the
- /// list \p L. Returns `#meta::npos` if the type \p T was not found.
- /// \par Complexity
- /// \f$ O(N) \f$.
- /// \ingroup query
- /// \sa `#meta::npos`
- template <META_TYPE_CONSTRAINT(list_like) L, typename T>
- using reverse_find_index = _t<detail::reverse_find_index_<L, T>>;
-
- namespace lazy
- {
- /// \sa 'meta::reverse_find_index'
- /// \ingroup lazy_query
- template <typename L, typename T>
- using reverse_find_index = defer<reverse_find_index, L, T>;
- } // namespace lazy
-
- ////////////////////////////////////////////////////////////////////////////////////
- // find
- /// Return the tail of the list \p L starting at the first occurrence of
- /// \p T, if any such element exists; the empty list, otherwise.
- /// \par Complexity
- /// \f$ O(N) \f$.
- /// \ingroup query
- template <META_TYPE_CONSTRAINT(list_like) L, typename T>
- using find = drop<L, min<find_index<L, T>, size<L>>>;
-
- namespace lazy
- {
- /// \sa 'meta::find'
- /// \ingroup lazy_query
- template <typename L, typename T>
- using find = defer<find, L, T>;
- } // namespace lazy
-
- ////////////////////////////////////////////////////////////////////////////////////
- // reverse_find
- /// \cond
- namespace detail
- {
- template <typename L, typename T, typename State = list<>>
- struct reverse_find_
- {
- };
-
- template <typename T, typename State>
- struct reverse_find_<list<>, T, State>
- {
- using type = State;
- };
-
- template <typename Head, typename... L, typename T, typename State>
- struct reverse_find_<list<Head, L...>, T, State> : reverse_find_<list<L...>, T, State>
- {
- };
-
- template <typename... L, typename T, typename State>
- struct reverse_find_<list<T, L...>, T, State>
- : reverse_find_<list<L...>, T, list<T, L...>>
- {
- };
- } // namespace detail
- /// \endcond
-
- /// Return the tail of the list \p L starting at the last occurrence of \p T, if any such
- /// element exists; the empty list, otherwise.
- /// \par Complexity
- /// \f$ O(N) \f$.
- /// \ingroup query
- template <META_TYPE_CONSTRAINT(list_like) L, typename T>
- using reverse_find = drop<L, min<reverse_find_index<L, T>, size<L>>>;
-
- namespace lazy
- {
- /// \sa 'meta::rfind'
- /// \ingroup lazy_query
- template <typename L, typename T>
- using reverse_find = defer<reverse_find, L, T>;
- } // namespace lazy
-
- ///////////////////////////////////////////////////////////////////////////////////////////
- // find_if
- /// \cond
- namespace detail
- {
- #ifdef META_CONCEPT
- template <typename L, typename Fn>
- struct find_if_
- {
- };
-
- template <typename Fn>
- struct find_if_<list<>, Fn>
- {
- using type = list<>;
- };
-
- template <typename Head, typename... L, typename Fn>
- requires integral<invoke<Fn, Head>>
- struct find_if_<list<Head, L...>, Fn>
- : if_<invoke<Fn, Head>, id<list<Head, L...>>, find_if_<list<L...>, Fn>>
- {
- };
- #else
- constexpr bool const *find_if_i_(bool const *const begin, bool const *const end)
- {
- return begin == end || *begin ? begin : find_if_i_(begin + 1, end);
- }
-
- template <typename L, typename Fn, typename = void>
- struct find_if_
- {
- };
-
- template <typename Fn>
- struct find_if_<list<>, Fn>
- {
- using type = list<>;
- };
-
- template <typename... L, typename Fn>
- struct find_if_<list<L...>, Fn,
- void_<integer_sequence<bool, bool(invoke<Fn, L>::type::value)...>>>
- {
- #ifdef META_WORKAROUND_LLVM_28385
- static constexpr bool s_v[sizeof...(L)] = {invoke<Fn, L>::type::value...};
- #else
- static constexpr bool s_v[] = {invoke<Fn, L>::type::value...};
- #endif
- using type =
- drop_c<list<L...>, detail::find_if_i_(s_v, s_v + sizeof...(L)) - s_v>;
- };
- #endif
- } // namespace detail
- /// \endcond
-
- /// Return the tail of the list \p L starting at the first element `A`
- /// such that `invoke<Fn, A>::%value` is \c true, if any such element
- /// exists; the empty list, otherwise.
- /// \par Complexity
- /// \f$ O(N) \f$.
- /// \ingroup query
- template <META_TYPE_CONSTRAINT(list_like) L, META_TYPE_CONSTRAINT(invocable) Fn>
- using find_if = _t<detail::find_if_<L, Fn>>;
-
- namespace lazy
- {
- /// \sa 'meta::find_if'
- /// \ingroup lazy_query
- template <typename L, typename Fn>
- using find_if = defer<find_if, L, Fn>;
- } // namespace lazy
-
- ////////////////////////////////////////////////////////////////////////////////////
- // reverse_find_if
- /// \cond
- namespace detail
- {
- #ifdef META_CONCEPT
- template <typename L, typename Fn, typename State = list<>>
- struct reverse_find_if_
- {
- };
-
- template <typename Fn, typename State>
- struct reverse_find_if_<list<>, Fn, State>
- {
- using type = State;
- };
-
- template <typename Head, typename... L, typename Fn, typename State>
- requires integral<invoke<Fn, Head>>
- struct reverse_find_if_<list<Head, L...>, Fn, State>
- : reverse_find_if_<list<L...>, Fn, if_<invoke<Fn, Head>, list<Head, L...>, State>>
- {
- };
- #else
- constexpr bool const *reverse_find_if_i_(bool const *const begin, bool const *const pos,
- bool const *const end)
- {
- return begin == pos
- ? end
- : *(pos - 1) ? pos - 1 : reverse_find_if_i_(begin, pos - 1, end);
- }
-
- template <typename L, typename Fn, typename = void>
- struct reverse_find_if_
- {
- };
-
- template <typename Fn>
- struct reverse_find_if_<list<>, Fn>
- {
- using type = list<>;
- };
-
- template <typename... L, typename Fn>
- struct reverse_find_if_<
- list<L...>, Fn,
- void_<integer_sequence<bool, bool(invoke<Fn, L>::type::value)...>>>
- {
- #ifdef META_WORKAROUND_LLVM_28385
- static constexpr bool s_v[sizeof...(L)] = {invoke<Fn, L>::type::value...};
- #else
- static constexpr bool s_v[] = {invoke<Fn, L>::type::value...};
- #endif
- using type =
- drop_c<list<L...>, detail::reverse_find_if_i_(s_v, s_v + sizeof...(L),
- s_v + sizeof...(L)) -
- s_v>;
- };
- #endif
- } // namespace detail
- /// \endcond
-
- /// Return the tail of the list \p L starting at the last element `A`
- /// such that `invoke<Fn, A>::%value` is \c true, if any such element
- /// exists; the empty list, otherwise.
- /// \par Complexity
- /// \f$ O(N) \f$.
- /// \ingroup query
- template <META_TYPE_CONSTRAINT(list_like) L, META_TYPE_CONSTRAINT(invocable) Fn>
- using reverse_find_if = _t<detail::reverse_find_if_<L, Fn>>;
-
- namespace lazy
- {
- /// \sa 'meta::rfind_if'
- /// \ingroup lazy_query
- template <typename L, typename Fn>
- using reverse_find_if = defer<reverse_find_if, L, Fn>;
- } // namespace lazy
-
- ///////////////////////////////////////////////////////////////////////////////////////////
- // replace
- /// \cond
- namespace detail
- {
- template <typename L, typename T, typename U>
- struct replace_
- {
- };
-
- template <typename... L, typename T, typename U>
- struct replace_<list<L...>, T, U>
- {
- using type = list<if_c<META_IS_SAME(T, L), U, L>...>;
- };
- } // namespace detail
- /// \endcond
-
- /// Return a new \c meta::list where all instances of type \p T have
- /// been replaced with \p U.
- /// \par Complexity
- /// \f$ O(N) \f$.
- /// \ingroup transformation
- template <META_TYPE_CONSTRAINT(list_like) L, typename T, typename U>
- using replace = _t<detail::replace_<L, T, U>>;
-
- namespace lazy
- {
- /// \sa 'meta::replace'
- /// \ingroup lazy_transformation
- template <typename L, typename T, typename U>
- using replace = defer<replace, T, U>;
- } // namespace lazy
-
- ///////////////////////////////////////////////////////////////////////////////////////////
- // replace_if
- /// \cond
- namespace detail
- {
- #ifdef META_CONCEPT
- template <typename L, typename C, typename U>
- struct replace_if_
- {
- };
-
- template <typename... L, typename C, typename U>
- requires and_v<integral<invoke<C, L>>...>
- struct replace_if_<list<L...>, C, U>
- {
- using type = list<if_<invoke<C, L>, U, L>...>;
- };
- #else
- template <typename L, typename C, typename U, typename = void>
- struct replace_if_
- {
- };
-
- template <typename... L, typename C, typename U>
- struct replace_if_<list<L...>, C, U,
- void_<integer_sequence<bool, bool(invoke<C, L>::type::value)...>>>
- {
- using type = list<if_<invoke<C, L>, U, L>...>;
- };
- #endif
- } // namespace detail
- /// \endcond
-
- /// Return a new \c meta::list where all elements \c A of the list \p L
- /// for which `invoke<C,A>::%value` is \c true have been replaced with
- /// \p U.
- /// \par Complexity
- /// \f$ O(N) \f$.
- /// \ingroup transformation
- template <META_TYPE_CONSTRAINT(list_like) L, typename C, typename U>
- using replace_if = _t<detail::replace_if_<L, C, U>>;
-
- namespace lazy
- {
- /// \sa 'meta::replace_if'
- /// \ingroup lazy_transformation
- template <typename L, typename C, typename U>
- using replace_if = defer<replace_if, C, U>;
- } // namespace lazy
-
- ///////////////////////////////////////////////////////////////////////////////////////
- // count
- namespace detail
- {
- template <typename, typename>
- struct count_
- {
- };
-
- #if (defined(META_CONCEPT) || META_CXX_VARIABLE_TEMPLATES) && META_CXX_FOLD_EXPRESSIONS
- template <typename... Ts, typename T>
- struct count_<list<Ts...>, T>
- {
- using type = meta::size_t<((std::size_t)META_IS_SAME(T, Ts) + ...)>;
- };
- #else
- constexpr std::size_t count_i_(bool const *const begin, bool const *const end,
- std::size_t n)
- {
- return begin == end ? n : detail::count_i_(begin + 1, end, n + *begin);
- }
-
- template <typename T>
- struct count_<list<>, T>
- {
- using type = meta::size_t<0>;
- };
-
- template <typename... L, typename T>
- struct count_<list<L...>, T>
- {
- #ifdef META_WORKAROUND_LLVM_28385
- static constexpr bool s_v[sizeof...(L)] = {META_IS_SAME(T, L)...};
- #else
- static constexpr bool s_v[] = {META_IS_SAME(T, L)...};
- #endif
- using type = meta::size_t<detail::count_i_(s_v, s_v + sizeof...(L), 0u)>;
- };
- #endif
- } // namespace detail
-
- /// Count the number of times a type \p T appears in the list \p L.
- /// \par Complexity
- /// \f$ O(N) \f$.
- /// \ingroup query
- template <META_TYPE_CONSTRAINT(list_like) L, typename T>
- using count = _t<detail::count_<L, T>>;
-
- namespace lazy
- {
- /// \sa `meta::count`
- /// \ingroup lazy_query
- template <typename L, typename T>
- using count = defer<count, L, T>;
- } // namespace lazy
-
- ///////////////////////////////////////////////////////////////////////////////////////
- // count_if
- namespace detail
- {
- #if defined(META_CONCEPT) && META_CXX_FOLD_EXPRESSIONS
- template <typename, typename>
- struct count_if_
- {
- };
-
- template <typename... Ts, typename Fn>
- requires (integral<invoke<Fn, Ts>> && ...)
- struct count_if_<list<Ts...>, Fn>
- {
- using type = meta::size_t<((std::size_t)(bool)_v<invoke<Fn, Ts>> + ...)>;
- };
- #else
- template <typename L, typename Fn, typename = void>
- struct count_if_
- {
- };
-
- template <typename Fn>
- struct count_if_<list<>, Fn>
- {
- using type = meta::size_t<0>;
- };
-
- template <typename... L, typename Fn>
- struct count_if_<list<L...>, Fn,
- void_<integer_sequence<bool, bool(invoke<Fn, L>::type::value)...>>>
- {
- #if META_CXX_FOLD_EXPRESSIONS
- using type = meta::size_t<((std::size_t)(bool)invoke<Fn, L>::type::value + ...)>;
- #else
- #ifdef META_WORKAROUND_LLVM_28385
- static constexpr bool s_v[sizeof...(L)] = {invoke<Fn, L>::type::value...};
- #else
- static constexpr bool s_v[] = {invoke<Fn, L>::type::value...};
- #endif
- using type = meta::size_t<detail::count_i_(s_v, s_v + sizeof...(L), 0u)>;
- #endif // META_CXX_FOLD_EXPRESSIONS
- };
- #endif // META_CONCEPT
- } // namespace detail
-
- /// Count the number of times the predicate \p Fn evaluates to true for all the elements in
- /// the list \p L.
- /// \par Complexity
- /// \f$ O(N) \f$.
- /// \ingroup query
- template <META_TYPE_CONSTRAINT(list_like) L, META_TYPE_CONSTRAINT(invocable) Fn>
- using count_if = _t<detail::count_if_<L, Fn>>;
-
- namespace lazy
- {
- /// \sa `meta::count_if`
- /// \ingroup lazy_query
- template <typename L, typename Fn>
- using count_if = defer<count_if, L, Fn>;
- } // namespace lazy
-
- ///////////////////////////////////////////////////////////////////////////////////////////
- // filter
- /// \cond
- namespace detail
- {
- template <typename Pred>
- struct filter_
- {
- template <typename A>
- using invoke = if_c<invoke<Pred, A>::type::value, list<A>, list<>>;
- };
- } // namespace detail
- /// \endcond
-
- /// Returns a new meta::list where only those elements of \p L that satisfy the
- /// Callable \p Pred such that `invoke<Pred,A>::%value` is \c true are present.
- /// That is, those elements that don't satisfy the \p Pred are "removed".
- /// \par Complexity
- /// \f$ O(N) \f$.
- /// \ingroup transformation
- template <typename L, typename Pred>
- using filter = join<transform<L, detail::filter_<Pred>>>;
-
- namespace lazy
- {
- /// \sa 'meta::filter'
- /// \ingroup lazy_transformation
- template <typename L, typename Fn>
- using filter = defer<filter, L, Fn>;
- } // namespace lazy
-
- ///////////////////////////////////////////////////////////////////////////////////////////
- // static_const
- ///\cond
- namespace detail
- {
- template <typename T>
- struct static_const
- {
- static constexpr T value{};
- };
-
- // Avoid potential ODR violations with global objects:
- template <typename T>
- constexpr T static_const<T>::value;
- } // namespace detail
-
- ///\endcond
-
- ///////////////////////////////////////////////////////////////////////////////////////////
- // for_each
- /// \cond
- namespace detail
- {
- struct for_each_fn
- {
- template <class Fn, class... Args>
- constexpr auto operator()(list<Args...>, Fn f) const -> Fn
- {
- return (void)std::initializer_list<int>{((void)f(Args{}), 0)...}, f;
- }
- };
- } // namespace detail
- /// \endcond
-
- #if META_CXX_INLINE_VARIABLES
- /// `for_each(L, Fn)` calls the \p Fn for each
- /// argument in the \p L.
- /// \ingroup runtime
- inline constexpr detail::for_each_fn for_each{};
- #else
- ///\cond
- namespace
- {
- /// \endcond
-
- /// `for_each(List, UnaryFunction)` calls the \p UnaryFunction for each
- /// argument in the \p List.
- /// \ingroup runtime
- constexpr auto &&for_each = detail::static_const<detail::for_each_fn>::value;
-
- /// \cond
- }
- /// \endcond
- #endif
-
- ///////////////////////////////////////////////////////////////////////////////////////////
- // transpose
- /// Given a list of lists of types \p ListOfLists, transpose the elements from the lists.
- /// \par Complexity
- /// \f$ O(N \times M) \f$, where \f$ N \f$ is the size of the outer list, and
- /// \f$ M \f$ is the size of the inner lists.
- /// \ingroup transformation
- template <META_TYPE_CONSTRAINT(list_like) ListOfLists>
- using transpose = fold<ListOfLists, repeat_n<size<front<ListOfLists>>, list<>>,
- bind_back<quote<transform>, quote<push_back>>>;
-
- namespace lazy
- {
- /// \sa 'meta::transpose'
- /// \ingroup lazy_transformation
- template <typename ListOfLists>
- using transpose = defer<transpose, ListOfLists>;
- } // namespace lazy
-
- ///////////////////////////////////////////////////////////////////////////////////////////
- // zip_with
- /// Given a list of lists of types \p ListOfLists and an invocable \p Fn, construct a new
- /// list by calling \p Fn with the elements from the lists pairwise.
- /// \par Complexity
- /// \f$ O(N \times M) \f$, where \f$ N \f$ is the size of the outer list, and
- /// \f$ M \f$ is the size of the inner lists.
- /// \ingroup transformation
- template <META_TYPE_CONSTRAINT(invocable) Fn, META_TYPE_CONSTRAINT(list_like) ListOfLists>
- using zip_with = transform<transpose<ListOfLists>, uncurry<Fn>>;
-
- namespace lazy
- {
- /// \sa 'meta::zip_with'
- /// \ingroup lazy_transformation
- template <typename Fn, typename ListOfLists>
- using zip_with = defer<zip_with, Fn, ListOfLists>;
- } // namespace lazy
-
- ///////////////////////////////////////////////////////////////////////////////////////////
- // zip
- /// Given a list of lists of types \p ListOfLists, construct a new list by grouping the
- /// elements from the lists pairwise into `meta::list`s.
- /// \par Complexity
- /// \f$ O(N \times M) \f$, where \f$ N \f$ is the size of the outer list, and \f$ M \f$
- /// is the size of the inner lists.
- /// \ingroup transformation
- template <META_TYPE_CONSTRAINT(list_like) ListOfLists>
- using zip = transpose<ListOfLists>;
-
- namespace lazy
- {
- /// \sa 'meta::zip'
- /// \ingroup lazy_transformation
- template <typename ListOfLists>
- using zip = defer<zip, ListOfLists>;
- } // namespace lazy
-
- ///////////////////////////////////////////////////////////////////////////////////////////
- // as_list
- /// \cond
- namespace detail
- {
- template <typename T>
- using uncvref_t = _t<std::remove_cv<_t<std::remove_reference<T>>>>;
-
- // Indirection here needed to avoid Core issue 1430
- // https://wg21.link/cwg1430
- template <typename Sequence>
- struct as_list_ : lazy::invoke<uncurry<quote<list>>, Sequence>
- {
- };
- } // namespace detail
- /// \endcond
-
- /// Turn a type into an instance of \c meta::list in a way determined by
- /// \c meta::apply.
- /// \ingroup list
- template <typename Sequence>
- using as_list = _t<detail::as_list_<detail::uncvref_t<Sequence>>>;
-
- namespace lazy
- {
- /// \sa 'meta::as_list'
- /// \ingroup lazy_list
- template <typename Sequence>
- using as_list = defer<as_list, Sequence>;
- } // namespace lazy
-
- ///////////////////////////////////////////////////////////////////////////////////////////
- // reverse
- /// \cond
- namespace detail
- {
- template <typename L, typename State = list<>>
- struct reverse_ : lazy::fold<L, State, quote<push_front>>
- {
- };
-
- template <typename T0, typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename... Ts,
- typename... Us>
- struct reverse_<list<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, Ts...>, list<Us...>>
- : reverse_<list<Ts...>, list<T9, T8, T7, T6, T5, T4, T3, T2, T1, T0, Us...>>
- {
- };
- }
- /// \endcond
-
- /// Return a new \c meta::list by reversing the elements in the list \p L.
- /// \par Complexity
- /// \f$ O(N) \f$.
- /// \ingroup transformation
- template <META_TYPE_CONSTRAINT(list_like) L>
- using reverse = _t<detail::reverse_<L>>;
-
- namespace lazy
- {
- /// \sa 'meta::reverse'
- /// \ingroup lazy_transformation
- template <typename L>
- using reverse = defer<reverse, L>;
- } // namespace lazy
-
- /// Logically negate the result of invocable \p Fn.
- /// \ingroup trait
- template <META_TYPE_CONSTRAINT(invocable) Fn>
- using not_fn = compose<quote<not_>, Fn>;
-
- namespace lazy
- {
- /// \sa 'meta::not_fn'
- /// \ingroup lazy_trait
- template <typename Fn>
- using not_fn = defer<not_fn, Fn>;
- } // namespace lazy
-
- ///////////////////////////////////////////////////////////////////////////////////////////
- // all_of
- /// A Boolean integral constant wrapper around \c true if `invoke<Fn, A>::%value` is \c true
- /// for all elements \c A in \c meta::list \p L; \c false, otherwise.
- /// \par Complexity
- /// \f$ O(N) \f$.
- /// \ingroup query
- template <META_TYPE_CONSTRAINT(list_like) L, META_TYPE_CONSTRAINT(invocable) Fn>
- using all_of = empty<find_if<L, not_fn<Fn>>>;
-
- namespace lazy
- {
- /// \sa 'meta::all_of'
- /// \ingroup lazy_query
- template <typename L, typename Fn>
- using all_of = defer<all_of, L, Fn>;
- } // namespace lazy
-
- ///////////////////////////////////////////////////////////////////////////////////////////
- // any_of
- /// A Boolean integral constant wrapper around \c true if `invoke<Fn, A>::%value` is
- /// \c true for any element \c A in \c meta::list \p L; \c false, otherwise.
- /// \par Complexity
- /// \f$ O(N) \f$.
- /// \ingroup query
- template <META_TYPE_CONSTRAINT(list_like) L, META_TYPE_CONSTRAINT(invocable) Fn>
- using any_of = not_<empty<find_if<L, Fn>>>;
-
- namespace lazy
- {
- /// \sa 'meta::any_of'
- /// \ingroup lazy_query
- template <typename L, typename Fn>
- using any_of = defer<any_of, L, Fn>;
- } // namespace lazy
-
- ///////////////////////////////////////////////////////////////////////////////////////////
- // none_of
- /// A Boolean integral constant wrapper around \c true if `invoke<Fn, A>::%value` is
- /// \c false for all elements \c A in \c meta::list \p L; \c false, otherwise.
- /// \par Complexity
- /// \f$ O(N) \f$.
- /// \ingroup query
- template <META_TYPE_CONSTRAINT(list_like) L, META_TYPE_CONSTRAINT(invocable) Fn>
- using none_of = empty<find_if<L, Fn>>;
-
- namespace lazy
- {
- /// \sa 'meta::none_of'
- /// \ingroup lazy_query
- template <typename L, META_TYPE_CONSTRAINT(invocable) Fn>
- using none_of = defer<none_of, L, Fn>;
- } // namespace lazy
-
- ///////////////////////////////////////////////////////////////////////////////////////////
- // in
- /// A Boolean integral constant wrapper around \c true if there is at least one occurrence
- /// of \p T in \p L.
- /// \par Complexity
- /// \f$ O(N) \f$.
- /// \ingroup query
- template <META_TYPE_CONSTRAINT(list_like) L, typename T>
- using in = not_<empty<find<L, T>>>;
-
- namespace lazy
- {
- /// \sa 'meta::in'
- /// \ingroup lazy_query
- template <typename L, typename T>
- using in = defer<in, L, T>;
- } // namespace lazy
-
- ///////////////////////////////////////////////////////////////////////////////////////////
- // inherit
- /// \cond
- namespace detail
- {
- template <typename L>
- struct inherit_
- {
- };
-
- template <typename... L>
- struct inherit_<list<L...>> : L...
- {
- using type = inherit_;
- };
- } // namespace detail
- /// \endcond
-
- /// A type that inherits from all the types in the list
- /// \pre The types in the list must be unique
- /// \pre All the types in the list must be non-final class types
- /// \ingroup datatype
- template <META_TYPE_CONSTRAINT(list_like) L>
- using inherit = meta::_t<detail::inherit_<L>>;
-
- namespace lazy
- {
- /// \sa 'meta::inherit'
- /// \ingroup lazy_datatype
- template <typename L>
- using inherit = defer<inherit, L>;
- } // namespace lazy
-
- ///////////////////////////////////////////////////////////////////////////////////////////
- // unique
- /// \cond
- namespace detail
- {
- template <typename Set, typename T>
- struct in_
- {
- };
-
- template <typename... Set, typename T>
- struct in_<list<Set...>, T> : bool_<META_IS_BASE_OF(id<T>, inherit<list<id<Set>...>>)>
- {
- };
-
- template <typename Set, typename T>
- struct insert_back_
- {
- };
-
- template <typename... Set, typename T>
- struct insert_back_<list<Set...>, T>
- {
- using type = if_<in_<list<Set...>, T>, list<Set...>, list<Set..., T>>;
- };
- } // namespace detail
- /// \endcond
-
- /// Return a new \c meta::list where all duplicate elements have been removed.
- /// \par Complexity
- /// \f$ O(N^2) \f$.
- /// \ingroup transformation
- template <META_TYPE_CONSTRAINT(list_like) L>
- using unique = fold<L, list<>, quote_trait<detail::insert_back_>>;
-
- namespace lazy
- {
- /// \sa 'meta::unique'
- /// \ingroup lazy_transformation
- template <typename L>
- using unique = defer<unique, L>;
- } // namespace lazy
-
- ///////////////////////////////////////////////////////////////////////////////////////////
- // partition
- /// \cond
- namespace detail
- {
- template <typename Fn>
- struct partition_
- {
- #ifdef META_CONCEPT
- template <typename, typename>
- #else
- template <typename, typename, typename = void>
- #endif
- struct impl
- {
- };
- template <typename... Yes, typename... No, typename A>
- #ifdef META_CONCEPT
- requires integral<invoke<Fn, A>>
- struct impl<pair<list<Yes...>, list<No...>>, A>
- #else
- struct impl<pair<list<Yes...>, list<No...>>, A,
- void_<bool_<invoke<Fn, A>::type::value>>>
- #endif
- {
- using type = if_<invoke<Fn, A>, pair<list<Yes..., A>, list<No...>>,
- pair<list<Yes...>, list<No..., A>>>;
- };
-
- template <typename State, typename A>
- using invoke = _t<impl<State, A>>;
- };
- } // namespace detail
- /// \endcond
-
- /// Returns a pair of lists, where the elements of \p L that satisfy the
- /// invocable \p Fn such that `invoke<Fn,A>::%value` is \c true are present in the
- /// first list and the rest are in the second.
- /// \par Complexity
- /// \f$ O(N) \f$.
- /// \ingroup transformation
- template <META_TYPE_CONSTRAINT(list_like) L, META_TYPE_CONSTRAINT(invocable) Fn>
- using partition = fold<L, pair<list<>, list<>>, detail::partition_<Fn>>;
-
- namespace lazy
- {
- /// \sa 'meta::partition'
- /// \ingroup lazy_transformation
- template <typename L, typename Fn>
- using partition = defer<partition, L, Fn>;
- } // namespace lazy
-
- ///////////////////////////////////////////////////////////////////////////////////////////
- // sort
- /// \cond
- namespace detail
- {
- template <META_TYPE_CONSTRAINT(invocable) Fn, typename A, typename B, typename... Ts>
- using part_ = partition<list<B, Ts...>, bind_back<Fn, A>>;
- #ifdef META_CONCEPT
- template <list_like L, invocable Fn>
- #else
- template <typename, typename, typename = void>
- #endif
- struct sort_
- {
- };
- template <typename Fn>
- struct sort_<list<>, Fn>
- {
- using type = list<>;
- };
-
- template <typename A, typename Fn>
- struct sort_<list<A>, Fn>
- {
- using type = list<A>;
- };
-
- template <typename A, typename B, typename... Ts, typename Fn>
- #ifdef META_CONCEPT
- requires trait<sort_<first<part_<Fn, A, B, Ts...>>, Fn>> &&
- trait<sort_<second<part_<Fn, A, B, Ts...>>, Fn>>
- struct sort_<list<A, B, Ts...>, Fn>
- #else
- struct sort_<
- list<A, B, Ts...>, Fn,
- void_<_t<sort_<first<part_<Fn, A, B, Ts...>>, Fn>>>>
- #endif
- {
- using P = part_<Fn, A, B, Ts...>;
- using type = concat<_t<sort_<first<P>, Fn>>, list<A>, _t<sort_<second<P>, Fn>>>;
- };
- } // namespace detail
- /// \endcond
-
- // clang-format off
- /// Return a new \c meta::list that is sorted according to invocable predicate \p Fn.
- /// \par Complexity
- /// Expected: \f$ O(N log N) \f$
- /// Worst case: \f$ O(N^2) \f$.
- /// \code
- /// using L0 = list<char[5], char[3], char[2], char[6], char[1], char[5], char[10]>;
- /// using L1 = meta::sort<L0, lambda<_a, _b, lazy::less<lazy::sizeof_<_a>, lazy::sizeof_<_b>>>>;
- /// static_assert(std::is_same_v<L1, list<char[1], char[2], char[3], char[5], char[5], char[6], char[10]>>, "");
- /// \endcode
- /// \ingroup transformation
- // clang-format on
- template <META_TYPE_CONSTRAINT(list_like) L, META_TYPE_CONSTRAINT(invocable) Fn>
- using sort = _t<detail::sort_<L, Fn>>;
-
- namespace lazy
- {
- /// \sa 'meta::sort'
- /// \ingroup lazy_transformation
- template <typename L, typename Fn>
- using sort = defer<sort, L, Fn>;
- } // namespace lazy
-
- ////////////////////////////////////////////////////////////////////////////
- // lambda_
- /// \cond
- namespace detail
- {
- template <typename T, int = 0>
- struct protect_;
-
- template <typename, int = 0>
- struct vararg_;
-
- template <typename T, int = 0>
- struct is_valid_;
-
- // Returns which branch to evaluate
- template <typename If, typename... Ts>
- #ifdef META_CONCEPT
- using lazy_if_ = lazy::_t<defer<_if_, If, protect_<Ts>...>>;
- #else
- using lazy_if_ = lazy::_t<defer<_if_, list<If, protect_<Ts>...>>>;
- #endif
-
- template <typename A, typename T, typename Fn, typename Ts>
- struct subst1_
- {
- using type = list<list<T>>;
- };
- template <typename T, typename Fn, typename Ts>
- struct subst1_<Fn, T, Fn, Ts>
- {
- using type = list<>;
- };
- template <typename A, typename T, typename Fn, typename Ts>
- struct subst1_<vararg_<A>, T, Fn, Ts>
- {
- using type = list<Ts>;
- };
-
- template <typename As, typename Ts>
- using substitutions_ = push_back<
- join<transform<
- concat<As, repeat_n_c<size<Ts>{} + 2 - size<As>{}, back<As>>>,
- concat<Ts, repeat_n_c<2, back<As>>>,
- bind_back<quote_trait<subst1_>, back<As>, drop_c<Ts, size<As>{} - 2>>>>,
- list<back<As>>>;
-
- #if 0//def META_CONCEPT
- template <list_like As, list_like Ts>
- requires (_v<size<Ts>> + 2 >= _v<size<As>>)
- using substitutions = substitutions_<As, Ts>;
- #else // ^^^ concepts / no concepts vvv
- template <typename As, typename Ts>
- using substitutions =
- #ifdef META_WORKAROUND_MSVC_702792
- invoke<if_c<(size<Ts>::value + 2 >= size<As>::value), quote<substitutions_>>, As,
- Ts>;
- #else // ^^^ workaround ^^^ / vvv no workaround vvv
- invoke<if_c<(size<Ts>{} + 2 >= size<As>{}), quote<substitutions_>>, As, Ts>;
- #endif // META_WORKAROUND_MSVC_702792
- #endif // META_CONCEPT
-
- template <typename T>
- struct is_vararg_ : std::false_type
- {
- };
- template <typename T>
- struct is_vararg_<vararg_<T>> : std::true_type
- {
- };
-
- template <META_TYPE_CONSTRAINT(list_like) Tags>
- using is_variadic_ = is_vararg_<at<push_front<Tags, void>, dec<size<Tags>>>>;
-
- template <META_TYPE_CONSTRAINT(list_like) Tags, bool IsVariadic = is_variadic_<Tags>::value>
- struct lambda_;
-
- // Non-variadic lambda implementation
- template <typename... As>
- struct lambda_<list<As...>, false>
- {
- private:
- static constexpr std::size_t arity = sizeof...(As) - 1;
- using Tags = list<As...>; // Includes the lambda body as the last arg!
- using Fn = back<Tags>;
- template <typename T, META_TYPE_CONSTRAINT(list_like) Args>
- struct impl;
- template <typename T, META_TYPE_CONSTRAINT(list_like) Args>
- using lazy_impl_ = lazy::_t<defer<impl, T, protect_<Args>>>;
- #if 0//def META_CONCEPT
- template <typename, list_like>
- #else
- template <typename, typename, typename = void>
- #endif
- struct subst_
- {
- };
- template <template <typename...> class C, typename... Ts, typename Args>
- #if 0//def META_CONCEPT
- requires valid<C, _t<impl<Ts, Args>>...> struct subst_<defer<C, Ts...>, Args>
- #else
- struct subst_<defer<C, Ts...>, Args, void_<C<_t<impl<Ts, Args>>...>>>
- #endif
- {
- using type = C<_t<impl<Ts, Args>>...>;
- };
- template <typename T, template <T...> class C, T... Is, typename Args>
- #if 0//def META_CONCEPT
- requires valid_i<T, C, Is...> struct subst_<defer_i<T, C, Is...>, Args>
- #else
- struct subst_<defer_i<T, C, Is...>, Args, void_<C<Is...>>>
- #endif
- {
- using type = C<Is...>;
- };
- template <typename T, META_TYPE_CONSTRAINT(list_like) Args>
- struct impl : if_c<(reverse_find_index<Tags, T>() != npos()),
- lazy::at<Args, reverse_find_index<Tags, T>>, id<T>>
- {
- };
- template <typename T, typename Args>
- struct impl<protect_<T>, Args>
- {
- using type = T;
- };
- template <typename T, typename Args>
- struct impl<is_valid_<T>, Args>
- {
- using type = is_trait<impl<T, Args>>;
- };
- template <typename If, typename... Ts, typename Args>
- struct impl<defer<if_, If, Ts...>, Args> // Short-circuit if_
- : impl<lazy_impl_<lazy_if_<If, Ts...>, Args>, Args>
- {
- };
- template <typename B, typename... Bs, typename Args>
- struct impl<defer<and_, B, Bs...>, Args> // Short-circuit and_
- : impl<lazy_impl_<lazy_if_<B, lazy::and_<Bs...>, protect_<std::false_type>>, Args>,
- Args>
- {
- };
- template <typename B, typename... Bs, typename Args>
- struct impl<defer<or_, B, Bs...>, Args> // Short-circuit or_
- : impl<lazy_impl_<lazy_if_<B, protect_<std::true_type>, lazy::or_<Bs...>>, Args>,
- Args>
- {
- };
- template <template <typename...> class C, typename... Ts, typename Args>
- struct impl<defer<C, Ts...>, Args> : subst_<defer<C, Ts...>, Args>
- {
- };
- template <typename T, template <T...> class C, T... Is, typename Args>
- struct impl<defer_i<T, C, Is...>, Args> : subst_<defer_i<T, C, Is...>, Args>
- {
- };
- template <template <typename...> class C, typename... Ts, typename Args>
- struct impl<C<Ts...>, Args> : subst_<defer<C, Ts...>, Args>
- {
- };
- template <typename... Ts, typename Args>
- struct impl<lambda_<list<Ts...>, false>, Args>
- {
- using type = compose<uncurry<lambda_<list<As..., Ts...>, false>>,
- curry<bind_front<quote<concat>, Args>>>;
- };
- template <typename... Bs, typename Args>
- struct impl<lambda_<list<Bs...>, true>, Args>
- {
- using type = compose<typename lambda_<list<As..., Bs...>, true>::thunk,
- bind_front<quote<concat>, transform<Args, quote<list>>>,
- curry<bind_front<quote<substitutions>, list<Bs...>>>>;
- };
-
- public:
- template <typename... Ts>
- #ifdef META_CONCEPT
- requires (sizeof...(Ts) == arity) using invoke = _t<impl<Fn, list<Ts..., Fn>>>;
- #else
- using invoke = _t<if_c<sizeof...(Ts) == arity, impl<Fn, list<Ts..., Fn>>>>;
- #endif
- };
-
- // Lambda with variadic placeholder (broken out due to less efficient compile-time
- // resource usage)
- template <typename... As>
- struct lambda_<list<As...>, true>
- {
- private:
- template <META_TYPE_CONSTRAINT(list_like) T, bool IsVar>
- friend struct lambda_;
- using Tags = list<As...>; // Includes the lambda body as the last arg!
- template <typename T, META_TYPE_CONSTRAINT(list_like) Args>
- struct impl;
- template <META_TYPE_CONSTRAINT(list_like) Args>
- using eval_impl_ = bind_back<quote_trait<impl>, Args>;
- template <typename T, META_TYPE_CONSTRAINT(list_like) Args>
- using lazy_impl_ = lazy::_t<defer<impl, T, protect_<Args>>>;
- template <template <typename...> class C, META_TYPE_CONSTRAINT(list_like) Args,
- META_TYPE_CONSTRAINT(list_like) Ts>
- using try_subst_ = apply<quote<C>, join<transform<Ts, eval_impl_<Args>>>>;
- #if 0//def META_CONCEPT
- template <typename, list_like>
- #else
- template <typename, typename, typename = void>
- #endif
- struct subst_
- {
- };
- template <template <typename...> class C, typename... Ts, typename Args>
- #if 0//def META_CONCEPT
- requires is_true<try_subst_<C, Args, list<Ts...>>> struct subst_<defer<C, Ts...>, Args>
- #else
- struct subst_<defer<C, Ts...>, Args, void_<try_subst_<C, Args, list<Ts...>>>>
- #endif
- {
- using type = list<try_subst_<C, Args, list<Ts...>>>;
- };
- template <typename T, template <T...> class C, T... Is, typename Args>
- #if 0//def META_CONCEPT
- requires valid_i<T, C, Is...> struct subst_<defer_i<T, C, Is...>, Args>
- #else
- struct subst_<defer_i<T, C, Is...>, Args, void_<C<Is...>>>
- #endif
- {
- using type = list<C<Is...>>;
- };
- template <typename T, META_TYPE_CONSTRAINT(list_like) Args>
- struct impl : if_c<(reverse_find_index<Tags, T>() != npos()),
- lazy::at<Args, reverse_find_index<Tags, T>>, id<list<T>>>
- {
- };
- template <typename T, typename Args>
- struct impl<protect_<T>, Args>
- {
- using type = list<T>;
- };
- template <typename T, typename Args>
- struct impl<is_valid_<T>, Args>
- {
- using type = list<is_trait<impl<T, Args>>>;
- };
- template <typename If, typename... Ts, typename Args>
- struct impl<defer<if_, If, Ts...>, Args> // Short-circuit if_
- : impl<lazy_impl_<lazy_if_<If, Ts...>, Args>, Args>
- {
- };
- template <typename B, typename... Bs, typename Args>
- struct impl<defer<and_, B, Bs...>, Args> // Short-circuit and_
- : impl<lazy_impl_<lazy_if_<B, lazy::and_<Bs...>, protect_<std::false_type>>, Args>,
- Args>
- {
- };
- template <typename B, typename... Bs, typename Args>
- struct impl<defer<or_, B, Bs...>, Args> // Short-circuit or_
- : impl<lazy_impl_<lazy_if_<B, protect_<std::true_type>, lazy::or_<Bs...>>, Args>,
- Args>
- {
- };
- template <template <typename...> class C, typename... Ts, typename Args>
- struct impl<defer<C, Ts...>, Args> : subst_<defer<C, Ts...>, Args>
- {
- };
- template <typename T, template <T...> class C, T... Is, typename Args>
- struct impl<defer_i<T, C, Is...>, Args> : subst_<defer_i<T, C, Is...>, Args>
- {
- };
- template <template <typename...> class C, typename... Ts, typename Args>
- struct impl<C<Ts...>, Args> : subst_<defer<C, Ts...>, Args>
- {
- };
- template <typename... Bs, bool IsVar, typename Args>
- struct impl<lambda_<list<Bs...>, IsVar>, Args>
- {
- using type =
- list<compose<typename lambda_<list<As..., Bs...>, true>::thunk,
- bind_front<quote<concat>, Args>,
- curry<bind_front<quote<substitutions>, list<Bs...>>>>>;
- };
- struct thunk
- {
- template <typename S, typename R = _t<impl<back<Tags>, S>>>
- #ifdef META_CONCEPT
- requires (_v<size<R>> == 1) using invoke = front<R>;
- #else
- using invoke = if_c<size<R>{} == 1, front<R>>;
- #endif
- };
-
- public:
- template <typename... Ts>
- using invoke = invoke<thunk, substitutions<Tags, list<Ts...>>>;
- };
- } // namespace detail
- /// \endcond
-
- ///////////////////////////////////////////////////////////////////////////////////////////
- // lambda
- /// For creating anonymous Invocables.
- /// \code
- /// using L = lambda<_a, _b, std::pair<_b, std::pair<_a, _a>>>;
- /// using P = invoke<L, int, short>;
- /// static_assert(std::is_same_v<P, std::pair<short, std::pair<int, int>>>, "");
- /// \endcode
- /// \ingroup trait
- template <typename... Ts>
- #ifdef META_CONCEPT
- requires (sizeof...(Ts) > 0) using lambda = detail::lambda_<list<Ts...>>;
- #else
- using lambda = if_c<(sizeof...(Ts) > 0), detail::lambda_<list<Ts...>>>;
- #endif
-
- ///////////////////////////////////////////////////////////////////////////////////////////
- // is_valid
- /// For testing whether a deferred computation will succeed in a \c let or a \c lambda.
- /// \ingroup trait
- template <typename T>
- using is_valid = detail::is_valid_<T>;
-
- ///////////////////////////////////////////////////////////////////////////////////////////
- // vararg
- /// For defining variadic placeholders.
- template <typename T>
- using vararg = detail::vararg_<T>;
-
- ///////////////////////////////////////////////////////////////////////////////////////////
- // protect
- /// For preventing the evaluation of a nested `defer`ed computation in a \c let or
- /// \c lambda expression.
- template <typename T>
- using protect = detail::protect_<T>;
-
- ///////////////////////////////////////////////////////////////////////////////////////////
- // var
- /// For use when defining local variables in \c meta::let expressions
- /// \sa `meta::let`
- template <typename Tag, typename Value>
- struct var;
-
- /// \cond
- namespace detail
- {
- template <typename...>
- struct let_
- {
- };
- template <typename Fn>
- struct let_<Fn>
- {
- using type = lazy::invoke<lambda<Fn>>;
- };
- template <typename Tag, typename Value, typename... Rest>
- struct let_<var<Tag, Value>, Rest...>
- {
- using type = lazy::invoke<lambda<Tag, _t<let_<Rest...>>>, Value>;
- };
- } // namespace detail
- /// \endcond
-
- /// A lexically scoped expression with local variables.
- ///
- /// \code
- /// template <typename T, typename L>
- /// using find_index_ = let<
- /// var<_a, L>,
- /// var<_b, lazy::find<_a, T>>,
- /// lazy::if_<
- /// std::is_same<_b, list<>>,
- /// meta::npos,
- /// lazy::minus<lazy::size<_a>, lazy::size<_b>>>>;
- /// static_assert(find_index_<int, list<short, int, float>>{} == 1, "");
- /// static_assert(find_index_<double, list<short, int, float>>{} == meta::npos{}, "");
- /// \endcode
- /// \ingroup trait
- template <typename... As>
- using let = _t<_t<detail::let_<As...>>>;
-
- namespace lazy
- {
- /// \sa `meta::let`
- /// \ingroup lazy_trait
- template <typename... As>
- using let = defer<let, As...>;
- } // namespace lazy
-
- // Some argument placeholders for use in \c lambda expressions.
- /// \ingroup trait
- inline namespace placeholders
- {
- // regular placeholders:
- struct _a;
- struct _b;
- struct _c;
- struct _d;
- struct _e;
- struct _f;
- struct _g;
- struct _h;
- struct _i;
-
- // variadic placeholders:
- using _args = vararg<void>;
- using _args_a = vararg<_a>;
- using _args_b = vararg<_b>;
- using _args_c = vararg<_c>;
- } // namespace placeholders
-
- ///////////////////////////////////////////////////////////////////////////////////////////
- // cartesian_product
- /// \cond
- namespace detail
- {
- template <typename M2, typename M>
- struct cartesian_product_fn
- {
- template <typename X>
- struct lambda0
- {
- template <typename Xs>
- using lambda1 = list<push_front<Xs, X>>;
- using type = join<transform<M2, quote<lambda1>>>;
- };
- using type = join<transform<M, quote_trait<lambda0>>>;
- };
- } // namespace detail
- /// \endcond
-
- /// Given a list of lists \p ListOfLists, return a new list of lists that is the Cartesian
- /// Product. Like the `sequence` function from the Haskell Prelude.
- /// \par Complexity
- /// \f$ O(N \times M) \f$, where \f$ N \f$ is the size of the outer list, and
- /// \f$ M \f$ is the size of the inner lists.
- /// \ingroup transformation
- template <META_TYPE_CONSTRAINT(list_like) ListOfLists>
- using cartesian_product =
- reverse_fold<ListOfLists, list<list<>>, quote_trait<detail::cartesian_product_fn>>;
-
- namespace lazy
- {
- /// \sa 'meta::cartesian_product'
- /// \ingroup lazy_transformation
- template <typename ListOfLists>
- using cartesian_product = defer<cartesian_product, ListOfLists>;
- } // namespace lazy
-
- /// \cond
- ///////////////////////////////////////////////////////////////////////////////////////////
- // add_const_if
- namespace detail
- {
- template <bool>
- struct add_const_if
- {
- template <typename T>
- using invoke = T const;
- };
- template <>
- struct add_const_if<false>
- {
- template <typename T>
- using invoke = T;
- };
- } // namespace detail
- template <bool If>
- using add_const_if_c = detail::add_const_if<If>;
- template <META_TYPE_CONSTRAINT(integral) If>
- using add_const_if = add_const_if_c<If::type::value>;
- /// \endcond
-
- /// \cond
- ///////////////////////////////////////////////////////////////////////////////////////////
- // const_if
- template <bool If, typename T>
- using const_if_c = typename add_const_if_c<If>::template invoke<T>;
- template <typename If, typename T>
- using const_if = typename add_const_if<If>::template invoke<T>;
- /// \endcond
-
- /// \cond
- namespace detail
- {
- template <typename State, typename Ch>
- using atoi_ = if_c<(Ch::value >= '0' && Ch::value <= '9'),
- std::integral_constant<typename State::value_type,
- State::value * 10 + (Ch::value - '0')>>;
- }
- /// \endcond
-
- inline namespace literals
- {
- /// A user-defined literal that generates objects of type \c meta::size_t.
- /// \ingroup integral
- template <char... Chs>
- constexpr fold<list<char_<Chs>...>, meta::size_t<0>, quote<detail::atoi_>>
- operator"" _z()
- {
- return {};
- }
- } // namespace literals
- } // namespace meta
-
- /// \cond
- // Non-portable forward declarations of standard containers
- #ifndef META_NO_STD_FORWARD_DECLARATIONS
- #if defined(__apple_build_version__) || (defined(__clang__) && __clang_major__ < 6)
- META_BEGIN_NAMESPACE_STD
- META_BEGIN_NAMESPACE_VERSION
- template <class>
- class META_TEMPLATE_VIS allocator;
- template <class, class>
- struct META_TEMPLATE_VIS pair;
- template <class>
- struct META_TEMPLATE_VIS hash;
- template <class>
- struct META_TEMPLATE_VIS less;
- template <class>
- struct META_TEMPLATE_VIS equal_to;
- template <class>
- struct META_TEMPLATE_VIS char_traits;
- #if defined(_GLIBCXX_USE_CXX11_ABI) && _GLIBCXX_USE_CXX11_ABI
- inline namespace __cxx11 {
- #endif
- template <class, class, class>
- class META_TEMPLATE_VIS basic_string;
- #if defined(_GLIBCXX_USE_CXX11_ABI) && _GLIBCXX_USE_CXX11_ABI
- }
- #endif
- META_END_NAMESPACE_VERSION
- META_BEGIN_NAMESPACE_CONTAINER
- #if defined(__GLIBCXX__)
- inline namespace __cxx11 {
- #endif
- template <class, class>
- class META_TEMPLATE_VIS list;
- #if defined(__GLIBCXX__)
- }
- #endif
- template <class, class>
- class META_TEMPLATE_VIS forward_list;
- template <class, class>
- class META_TEMPLATE_VIS vector;
- template <class, class>
- class META_TEMPLATE_VIS deque;
- template <class, class, class, class>
- class META_TEMPLATE_VIS map;
- template <class, class, class, class>
- class META_TEMPLATE_VIS multimap;
- template <class, class, class>
- class META_TEMPLATE_VIS set;
- template <class, class, class>
- class META_TEMPLATE_VIS multiset;
- template <class, class, class, class, class>
- class META_TEMPLATE_VIS unordered_map;
- template <class, class, class, class, class>
- class META_TEMPLATE_VIS unordered_multimap;
- template <class, class, class, class>
- class META_TEMPLATE_VIS unordered_set;
- template <class, class, class, class>
- class META_TEMPLATE_VIS unordered_multiset;
- template <class, class>
- class META_TEMPLATE_VIS queue;
- template <class, class, class>
- class META_TEMPLATE_VIS priority_queue;
- template <class, class>
- class META_TEMPLATE_VIS stack;
- META_END_NAMESPACE_CONTAINER
- META_END_NAMESPACE_STD
-
- namespace meta
- {
- namespace detail
- {
- template <typename T, typename A = std::allocator<T>>
- using std_list = std::list<T, A>;
- template <typename T, typename A = std::allocator<T>>
- using std_forward_list = std::forward_list<T, A>;
- template <typename T, typename A = std::allocator<T>>
- using std_vector = std::vector<T, A>;
- template <typename T, typename A = std::allocator<T>>
- using std_deque = std::deque<T, A>;
- template <typename T, typename C = std::char_traits<T>, typename A = std::allocator<T>>
- using std_basic_string = std::basic_string<T, C, A>;
- template <typename K, typename V, typename C = std::less<K>,
- typename A = std::allocator<std::pair<K const, V>>>
- using std_map = std::map<K, V, C, A>;
- template <typename K, typename V, typename C = std::less<K>,
- typename A = std::allocator<std::pair<K const, V>>>
- using std_multimap = std::multimap<K, V, C, A>;
- template <typename K, typename C = std::less<K>, typename A = std::allocator<K>>
- using std_set = std::set<K, C, A>;
- template <typename K, typename C = std::less<K>, typename A = std::allocator<K>>
- using std_multiset = std::multiset<K, C, A>;
- template <typename K, typename V, typename H = std::hash<K>,
- typename C = std::equal_to<K>,
- typename A = std::allocator<std::pair<K const, V>>>
- using std_unordered_map = std::unordered_map<K, V, H, C, A>;
- template <typename K, typename V, typename H = std::hash<K>,
- typename C = std::equal_to<K>,
- typename A = std::allocator<std::pair<K const, V>>>
- using std_unordered_multimap = std::unordered_multimap<K, V, H, C, A>;
- template <typename K, typename H = std::hash<K>, typename C = std::equal_to<K>,
- typename A = std::allocator<K>>
- using std_unordered_set = std::unordered_set<K, H, C, A>;
- template <typename K, typename H = std::hash<K>, typename C = std::equal_to<K>,
- typename A = std::allocator<K>>
- using std_unordered_multiset = std::unordered_multiset<K, H, C, A>;
- template <typename T, typename C = std_deque<T>>
- using std_queue = std::queue<T, C>;
- template <typename T, typename C = std_vector<T>,
- class D = std::less<typename C::value_type>>
- using std_priority_queue = std::priority_queue<T, C, D>;
- template <typename T, typename C = std_deque<T>>
- using std_stack = std::stack<T, C>;
- } // namespace detail
-
- template <>
- struct quote<::std::list> : quote<detail::std_list>
- {
- };
- template <>
- struct quote<::std::deque> : quote<detail::std_deque>
- {
- };
- template <>
- struct quote<::std::forward_list> : quote<detail::std_forward_list>
- {
- };
- template <>
- struct quote<::std::vector> : quote<detail::std_vector>
- {
- };
- template <>
- struct quote<::std::basic_string> : quote<detail::std_basic_string>
- {
- };
- template <>
- struct quote<::std::map> : quote<detail::std_map>
- {
- };
- template <>
- struct quote<::std::multimap> : quote<detail::std_multimap>
- {
- };
- template <>
- struct quote<::std::set> : quote<detail::std_set>
- {
- };
- template <>
- struct quote<::std::multiset> : quote<detail::std_multiset>
- {
- };
- template <>
- struct quote<::std::unordered_map> : quote<detail::std_unordered_map>
- {
- };
- template <>
- struct quote<::std::unordered_multimap> : quote<detail::std_unordered_multimap>
- {
- };
- template <>
- struct quote<::std::unordered_set> : quote<detail::std_unordered_set>
- {
- };
- template <>
- struct quote<::std::unordered_multiset> : quote<detail::std_unordered_multiset>
- {
- };
- template <>
- struct quote<::std::queue> : quote<detail::std_queue>
- {
- };
- template <>
- struct quote<::std::priority_queue> : quote<detail::std_priority_queue>
- {
- };
- template <>
- struct quote<::std::stack> : quote<detail::std_stack>
- {
- };
- } // namespace meta
-
- #endif
- #endif
- /// \endcond
-
- #ifdef __clang__
- #pragma GCC diagnostic pop
- #endif
- #endif
|