tutorial.hpp 193 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204
  1. // Copyright Louis Dionne 2013-2017
  2. // Distributed under the Boost Software License, Version 1.0.
  3. // (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
  4. /*!
  5. @mainpage User Manual
  6. @tableofcontents
  7. @section tutorial-description Description
  8. ------------------------------------------------------------------------------
  9. Hana is a header-only library for C++ metaprogramming suited for computations
  10. on both types and values. The functionality it provides is a superset of what
  11. is provided by the well established [Boost.MPL][] and [Boost.Fusion][]
  12. libraries. By leveraging C++11/14 implementation techniques and idioms,
  13. Hana boasts faster compilation times and runtime performance on par or better
  14. than previous metaprogramming libraries, while noticeably increasing the level
  15. of expressiveness in the process. Hana is easy to extend in a ad-hoc manner
  16. and it provides out-of-the-box inter-operation with Boost.Fusion, Boost.MPL
  17. and the standard library.
  18. @section tutorial-installation Prerequisites and installation
  19. ------------------------------------------------------------------------------
  20. Hana is a header-only library without external dependencies (not even the rest
  21. of Boost). Hence, using Hana in your own project is very easy. Basically, just
  22. download the project and add the `include/` directory to your compiler's header
  23. search path and you are done. However, if you want to cleanly install Hana, you
  24. have a couple of options:
  25. 1. __Install Boost__\n
  26. Hana is included in the [Boost][] distribution starting from Boost 1.61.0, so
  27. installing that will give you access to Hana.
  28. 2. __Use Homebrew__\n
  29. On Mac OS, Hana can be installed with [Homebrew][]:
  30. @code{.sh}
  31. brew install hana
  32. @endcode
  33. 3. __Install manually__\n
  34. You can download the code from the official GitHub [repository][Hana.repository]
  35. and install the library manually by issuing the following commands from the root
  36. of the project (requires [CMake][]):
  37. @code{.sh}
  38. mkdir build && cd build
  39. cmake ..
  40. cmake --build . --target install
  41. @endcode
  42. This will install Hana to the default install-directory for your platform
  43. (`/usr/local` for Unix, `C:/Program Files` for Windows). If you want to
  44. install Hana in a custom location, you can use
  45. @code{.sh}
  46. cmake .. -DCMAKE_INSTALL_PREFIX=/custom/install/prefix
  47. @endcode
  48. If you just want to contribute to Hana, you can see how to best setup your
  49. environment for development in the [README][Hana.hacking].
  50. @note
  51. - Both the manual installation and the Homebrew installation will also install
  52. a `HanaConfig.cmake` file for use with CMake and a `hana.pc` file for use with
  53. [pkg-config][].
  54. - Do not mix a standalone installation of Hana (i.e. Hana not installed through
  55. Boost) with a full installation of Boost. The Hana provided within Boost and
  56. the standalone one may clash, and you won't know which version is used where.
  57. This is asking for trouble.
  58. @subsection tutorial-installation-cmake Note for CMake users
  59. If you use [CMake][], depending on Hana has never been so easy. When installed,
  60. Hana creates a `HanaConfig.cmake` file that exports the `hana` interface library
  61. target with all the required settings. All you need is to install Hana (through
  62. Homebrew or manually), use `find_package(Hana)`, and then link your own targets
  63. against the `hana` target. Here is a minimal example of doing this:
  64. @snippet example/cmake_integration/CMakeLists.txt snip
  65. If you have installed Hana in a non-standard place, you might need to play with
  66. `CMAKE_PREFIX_PATH`. For example, this can happen if you "manually" install
  67. Hana locally to another project. In this case, you'll need to tell CMake where
  68. to find the `HanaConfig.cmake` file by using
  69. @code{cmake}
  70. list(APPEND CMAKE_PREFIX_PATH "${INSTALLATION_PREFIX_FOR_HANA}")
  71. or
  72. cmake ... -DCMAKE_PREFIX_PATH=${INSTALLATION_PREFIX_FOR_HANA}
  73. @endcode
  74. where `INSTALLATION_PREFIX_FOR_HANA` is the path to the place where Hana was
  75. installed.
  76. @subsection tutorial-installation-requirements Compiler requirements
  77. The library relies on a C++14 compiler and standard library, but nothing else
  78. is required. However, we only guarantee support for the compilers listed
  79. below, which are tested on an ongoing basis:
  80. Compiler/Toolchain | Status
  81. ------------------ | ------
  82. Clang >= 3.9.1 | Fully working; tested on each push to GitHub
  83. Xcode >= 9.1 | Fully working; tested on each push to GitHub
  84. GCC >= 6.0.0 | Fully working; tested on each push to GitHub
  85. VS2017 >= Update 7 | Fully working; tested on each push to GitHub
  86. More specifically, Hana requires a compiler/standard library supporting the
  87. following C++14 features (non-exhaustively):
  88. - Generic lambdas
  89. - Generalized `constexpr`
  90. - Variable templates
  91. - Automatically deduced return type
  92. - All the C++14 type traits from the `<type_traits>` header
  93. Using a compiler not listed above may work, but support for such compilers is
  94. not guaranteed. More information for specific platforms is available on
  95. [the wiki][Hana.wiki].
  96. @section tutorial-support Support
  97. ------------------------------------------------------------------------------
  98. If you have a problem, please review the [FAQ](@ref tutorial-rationales) and
  99. [the wiki][Hana.wiki]. Searching [the issues][Hana.issues] for your problem is
  100. also a good idea. If that doesn't help, feel free to chat with us in [Gitter][Hana.chat],
  101. or open a new issue. [StackOverflow][] with the [boost-hana][Hana.StackOverflow]
  102. tag is the preferred place to ask questions on usage. If you are encountering
  103. what you think is a bug, please open an issue.
  104. @section tutorial-introduction Introduction
  105. ------------------------------------------------------------------------------
  106. When Boost.MPL first appeared, it provided C++ programmers with a huge relief
  107. by abstracting tons of template hackery behind a workable interface. This
  108. breakthrough greatly contributed to making C++ template metaprogramming more
  109. mainstream, and today the discipline is deeply rooted in many serious projects.
  110. Recently, C++11 and C++14 brought many major changes to the language, some of
  111. which make metaprogramming much easier, while others drastically widen the
  112. design space for libraries. A natural question then arises: is it still
  113. desirable to have abstractions for metaprogramming, and if so, which ones?
  114. After investigating different options like the [MPL11][], the answer eventually
  115. came by itself in the form of a library; Hana. The key insight to Hana is that
  116. the manipulation of types and values are nothing but two sides of the same
  117. coin. By unifying both concepts, metaprogramming becomes easier and new
  118. exciting possibilities open before us.
  119. @subsection tutorial-introduction-quadrants C++ computational quadrants
  120. But to really understand what is Hana all about, it is essential to understand
  121. the different types of computations in C++. We will focus our attention on
  122. four different kinds of computations, even though a finer grained separation
  123. would be possible. First, we have runtime computations, which are the usual
  124. computations we use in C++. In that world, we have runtime containers,
  125. runtime functions and runtime algorithms:
  126. @snippet example/tutorial/introduction.cpp runtime
  127. The usual toolbox for programming within this quadrant is the C++ standard
  128. library, which provides reusable algorithms and containers operating at
  129. runtime. Since C++11, a second kind of computation is possible: `constexpr`
  130. computations. There, we have `constexpr` containers, `constexpr` functions
  131. and `constexpr` algorithms:
  132. @code{cpp}
  133. constexpr int factorial(int n) {
  134. return n == 0 ? 1 : n * factorial(n - 1);
  135. }
  136. template <typename T, std::size_t N, typename F>
  137. constexpr std::array<std::result_of_t<F(T)>, N>
  138. transform(std::array<T, N> array, F f) {
  139. // ...
  140. }
  141. constexpr std::array<int, 4> ints{{1, 2, 3, 4}};
  142. constexpr std::array<int, 4> facts = transform(ints, factorial);
  143. static_assert(facts == std::array<int, 4>{{1, 2, 6, 24}}, "");
  144. @endcode
  145. @note
  146. For the above code to actually work, `std::array`'s `operator==` would have to
  147. be marked `constexpr`, which is not the case (even in C++14).
  148. Basically, a `constexpr` computation is different from a runtime computation
  149. in that it is simple enough to be evaluated (interpreted, really) by the
  150. compiler. In general, any function that does not perform anything too
  151. _unfriendly_ to the compiler's evaluator (like throwing or allocating memory)
  152. can be marked `constexpr` without any further change. This makes `constexpr`
  153. computations very similar to runtime computations, except `constexpr`
  154. computations are more restricted and they gain the ability to be evaluated
  155. at compile-time. Unfortunately, there is no commonly used toolbox for
  156. `constexpr`-programming, i.e. there is no widely adopted "standard library"
  157. for `constexpr` programming. However, the [Sprout][] library may be worth
  158. checking out for those with some interest in `constexpr` computations.
  159. The third kind of computations are heterogeneous computations. Heterogeneous
  160. computations differ from normal computations in that instead of having
  161. containers holding homogeneous objects (all objects having the same type),
  162. the containers may hold objects with different types. Furthermore, functions
  163. in this quadrant of computation are _heterogeneous_ functions, which is a
  164. complicated way of talking about template functions. Similarly, we have
  165. heterogeneous algorithms that manipulate heterogeneous containers and
  166. functions:
  167. @snippet example/tutorial/introduction.cpp heterogeneous
  168. If manipulating heterogeneous containers seems overly weird to you, just think
  169. of it as glorified `std::tuple` manipulation. In a C++03 world, the go-to
  170. library for doing this kind of computation is [Boost.Fusion][], which provides
  171. several data structures and algorithms to manipulate heterogeneous collections
  172. of data. The fourth and last quadrant of computation that we'll be considering
  173. here is the quadrant of type-level computations. In this quadrant, we have
  174. type-level containers, type-level functions (usually called metafunctions)
  175. and type-level algorithms. Here, everything operates on types: containers hold
  176. types and metafunctions take types as arguments and return types as results.
  177. @snippet example/tutorial/introduction.cpp type-level
  178. The realm of type-level computations has been explored quite extensively, and
  179. the de-facto solution for type-level computations in C++03 is a library named
  180. [Boost.MPL][], which provides type-level containers and algorithms. For
  181. low-level type transformations, the metafunctions provided by the
  182. `<type_traits>` standard header can also be used since C++11.
  183. @subsection tutorial-quadrants-about What is this library about?
  184. So all is good, but what is this library actually about? Now that we have set
  185. the table by clarifying the kinds of computations available to us in C++, the
  186. answer might strike you as very simple. __The purpose of Hana is to merge the
  187. 3rd and the 4th quadrants of computation__. More specifically, Hana is a
  188. (long-winded) constructive proof that heterogeneous computations are strictly
  189. more powerful than type-level computations, and that we can therefore express
  190. any type-level computation by an equivalent heterogeneous computation. This
  191. construction is done in two steps. First, Hana is a fully featured library of
  192. heterogeneous algorithms and containers, a bit like a modernized Boost.Fusion.
  193. Secondly, Hana provides a way of translating any type-level computation into its
  194. equivalent heterogeneous computation and back, which allows the full machinery
  195. of heterogeneous computations to be reused for type-level computations without
  196. any code duplication. Of course, the biggest advantage of this unification is
  197. seen by the user, as you will witness by yourself.
  198. @section tutorial-quickstart Quick start
  199. ------------------------------------------------------------------------------
  200. The goal of this section is to introduce the main concepts of the library
  201. from a very high level and at a fairly rapid pace; don't worry if you don't
  202. understand everything that's about to be thrown at you. However, this tutorial
  203. assumes the reader is already at least _familiar_ with basic metaprogramming
  204. and the [C++14 standard][C++14]. First, let's include the library:
  205. @snippet example/tutorial/quickstart.cpp includes
  206. Unless specified otherwise, the documentation assumes the above lines to be
  207. present before examples and code snippets. Also note that finer grained
  208. headers are provided and will be explained in the [Header organization]
  209. (@ref tutorial-header_organization) section. For the purpose of the
  210. quickstart, let's now include some additional headers and define some
  211. lovely animal types that we'll need below:
  212. @snippet example/tutorial/quickstart.cpp additional_setup
  213. If you are reading this documentation, chances are you already know
  214. `std::tuple` and `std::make_tuple`. Hana provides its own tuple and
  215. `make_tuple`:
  216. @snippet example/tutorial/quickstart.cpp animals
  217. This creates a tuple, which is like an array, except that it can hold elements
  218. with different types. Containers that can hold elements with different types
  219. such as this are called heterogeneous containers. While the standard library
  220. provides very few operations to manipulate `std::tuple`s, Hana provides several
  221. operations and algorithms to manipulate its own tuples:
  222. @snippet example/tutorial/quickstart.cpp algorithms
  223. @note
  224. `1_c` is a [C++14 user-defined literal][C++14.udl] creating a
  225. [compile-time number](@ref tutorial-integral). These user-defined
  226. literals are contained in the `boost::hana::literals` namespace,
  227. hence the `using` directive.
  228. Notice how we pass a [C++14 generic lambda][C++14.glambda] to `transform`;
  229. this is required because the lambda will first be called with a `Fish`, then
  230. a `Cat`, and finally a `Dog`, which all have different types. Hana provides
  231. most of the algorithms provided by the C++ standard library, except they work
  232. on tuples and related heterogeneous containers instead of `std::vector` &
  233. friends. In addition to working with heterogeneous values, Hana makes it
  234. possible to perform type-level computations with a natural syntax, all at
  235. compile-time and with no overhead whatsoever. This compiles and does just
  236. what you would expect:
  237. @snippet example/tutorial/quickstart.cpp type-level
  238. @note
  239. `type_c<...>` is not a type! It is a [C++14 variable template][C++14.vtemplate]
  240. yielding an object representing a type for Hana. This is explained in the
  241. section on [type computations](@ref tutorial-type).
  242. In addition to heterogeneous and compile-time sequences, Hana provides several
  243. features to make your metaprogramming nightmares a thing of the past. For
  244. example, one can check for the existence of a struct member with one easy
  245. line instead of relying on [clunky SFINAE hacks][SO.sfinae]:
  246. @snippet example/tutorial/quickstart.cpp has_name
  247. Writing a serialization library? Stop crying, we've got you covered.
  248. Reflection can be added to user-defined types very easily. This allows
  249. iterating over the members of a user-defined type, querying members with
  250. a programmatic interface and much more, without any runtime overhead:
  251. @snippet example/tutorial/quickstart.cpp serialization
  252. That's cool, but I can already hear you complaining about incomprehensible
  253. error messages. However, it turns out Hana was built for humans, not
  254. professional template metaprogrammers, and this shows. Let's intentionally
  255. screw up and see what kind of mess is thrown at us. First, the mistake:
  256. @snippet example/tutorial/quickstart.cpp screw_up
  257. Now, the punishment:
  258. @code{cpp}
  259. error: static_assert failed "hana::for_each(xs, f) requires 'xs' to be Foldable"
  260. static_assert(Foldable<S>::value,
  261. ^ ~~~~~~~~~~~~~~~~~~
  262. note: in instantiation of function template specialization
  263. 'boost::hana::for_each_t::operator()<
  264. std::__1::basic_ostream<char> &, (lambda at [snip])>' requested here
  265. hana::for_each(os, [&](auto member) {
  266. ^
  267. note: in instantiation of function template specialization
  268. 'main()::(anonymous class)::operator()<Person>' requested here
  269. serialize(std::cout, john);
  270. ^
  271. @endcode
  272. Not that bad, right? However, since small examples are very good to show off
  273. without actually doing something useful, let's examine a real world example.
  274. @subsection tutorial-quickstart-any A real world example
  275. In this section our goal will be to implement a kind of `switch` statement
  276. able to process `boost::any`s. Given a `boost::any`, the goal is to dispatch
  277. to the function associated to the dynamic type of the `any`:
  278. @snippet example/tutorial/quickstart.switchAny.cpp usage
  279. @note
  280. In the documentation, we will often use the `s` suffix on string literals to
  281. create `std::string`s without syntactic overhead. This is a standard-defined
  282. [C++14 user-defined literal][C++14.udl].
  283. Since the any holds a `char`, the second function is called with the `char`
  284. inside it. If the `any` had held an `int` instead, the first function would
  285. have been called with the `int` inside it. When the dynamic type of the `any`
  286. does not match any of the covered cases, the `%default_` function is called
  287. instead. Finally, the result of the `switch` is the result of calling the
  288. function associated to the `any`'s dynamic type. The type of that result is
  289. inferred to be the common type of the result of all the provided functions:
  290. @snippet example/tutorial/quickstart.switchAny.cpp result_inference
  291. We'll now look at how this utility can be implemented using Hana. The first
  292. step is to associate each type to a function. To do so, we represent each
  293. `case_` as a `hana::pair` whose first element is a type and whose second
  294. element is a function. Furthermore, we (arbitrarily) decide to represent the
  295. `%default_` case as a `hana::pair` mapping a dummy type to a function:
  296. @snippet example/tutorial/quickstart.switchAny.cpp cases
  297. To provide the interface we showed above, `switch_` will have to return a
  298. function taking the cases. In other words, `switch_(a)` must be a function
  299. taking any number of cases (which are `hana::pair`s), and performing the logic
  300. to dispatch `a` to the right function. This can easily be achieved by having
  301. `switch_` return a C++14 generic lambda:
  302. @code{cpp}
  303. template <typename Any>
  304. auto switch_(Any& a) {
  305. return [&a](auto ...cases_) {
  306. // ...
  307. };
  308. }
  309. @endcode
  310. However, since parameter packs are not very flexible, we'll put the cases
  311. into a tuple so we can manipulate them:
  312. @code{cpp}
  313. template <typename Any>
  314. auto switch_(Any& a) {
  315. return [&a](auto ...cases_) {
  316. auto cases = hana::make_tuple(cases_...);
  317. // ...
  318. };
  319. }
  320. @endcode
  321. Notice how the `auto` keyword is used when defining `cases`; it is often
  322. easier to let the compiler deduce the type of the tuple and use `make_tuple`
  323. instead of working out the types manually. The next step is to separate the
  324. default case from the rest of the cases. This is where things start to get
  325. interesting. To do so, we use Hana's `find_if` algorithm, which works a bit
  326. like `std::find_if`:
  327. @code{cpp}
  328. template <typename Any>
  329. auto switch_(Any& a) {
  330. return [&a](auto ...cases_) {
  331. auto cases = hana::make_tuple(cases_...);
  332. auto default_ = hana::find_if(cases, [](auto const& c) {
  333. return hana::first(c) == hana::type_c<default_t>;
  334. });
  335. // ...
  336. };
  337. }
  338. @endcode
  339. `find_if` takes a `tuple` and a predicate, and returns the first element of
  340. the tuple which satisfies the predicate. The result is returned as a
  341. `hana::optional`, which is very similar to a `std::optional`, except
  342. whether that optional value is empty or not is known at compile-time. If the
  343. predicate is not satisfied for any element of the `tuple`, `find_if` returns
  344. `nothing` (an empty value). Otherwise, it returns `just(x)` (a non-empty value),
  345. where `x` is the first element satisfying the predicate. Unlike predicates
  346. used in STL algorithms, the predicate used here must be generic because the
  347. tuple's elements are heterogeneous. Furthermore, that predicate must return
  348. what Hana calls an `IntegralConstant`, which means that the predicate's result
  349. must be known at compile-time. These details are explained in the section on
  350. [cross-phase algorithms](@ref tutorial-algorithms-cross_phase). Inside the
  351. predicate, we simply compare the type of the case's first element to
  352. `type_c<default_t>`. If you recall that we were using `hana::pair`s to encode
  353. cases, this simply means that we're finding the default case among all of the
  354. provided cases. But what if no default case was provided? We should fail at
  355. compile-time, of course!
  356. @code{cpp}
  357. template <typename Any>
  358. auto switch_(Any& a) {
  359. return [&a](auto ...cases_) {
  360. auto cases = hana::make_tuple(cases_...);
  361. auto default_ = hana::find_if(cases, [](auto const& c) {
  362. return hana::first(c) == hana::type_c<default_t>;
  363. });
  364. static_assert(default_ != hana::nothing,
  365. "switch is missing a default_ case");
  366. // ...
  367. };
  368. }
  369. @endcode
  370. Notice how we can use `static_assert` on the result of the comparison with
  371. `nothing`, even though `%default_` is a non-`constexpr` object? Boldly, Hana
  372. makes sure that no information that's known at compile-time is lost to the
  373. runtime, which is clearly the case of the presence of a `%default_` case.
  374. The next step is to gather the set of non-default cases. To achieve this, we
  375. use the `filter` algorithm, which keeps only the elements of the sequence
  376. satisfying the predicate:
  377. @code{cpp}
  378. template <typename Any>
  379. auto switch_(Any& a) {
  380. return [&a](auto ...cases_) {
  381. auto cases = hana::make_tuple(cases_...);
  382. auto default_ = hana::find_if(cases, [](auto const& c) {
  383. return hana::first(c) == hana::type_c<default_t>;
  384. });
  385. static_assert(default_ != hana::nothing,
  386. "switch is missing a default_ case");
  387. auto rest = hana::filter(cases, [](auto const& c) {
  388. return hana::first(c) != hana::type_c<default_t>;
  389. });
  390. // ...
  391. };
  392. }
  393. @endcode
  394. The next step is to find the first case matching the dynamic type of the `any`,
  395. and then call the function associated to that case. The simplest way to do this
  396. is to use classic recursion with variadic parameter packs. Of course, we could
  397. probably intertwine Hana algorithms in a convoluted way to achieve this, but
  398. sometimes the best way to do something is to write it from scratch using basic
  399. techniques. To do so, we'll call an implementation function with the contents
  400. of the `rest` tuple by using the `unpack` function:
  401. @snippet example/tutorial/quickstart.switchAny.cpp switch_
  402. `unpack` takes a `tuple` and a function, and calls the function with the content
  403. of the `tuple` as arguments. The result of `unpack` is the result of calling that
  404. function. In our case, the function is a generic lambda which in turn calls the
  405. `process` function. Our reason for using `unpack` here was to turn the `rest`
  406. tuple into a parameter pack of arguments, which are easier to process recursively
  407. than tuples. Before we move on to the `process` function, it is worthwhile to
  408. explain what `second(*%default_)` is all about. As we explained earlier,
  409. `%default_` is an optional value. Like `std::optional`, this optional value
  410. overloads the dereference operator (and the arrow operator) to allow accessing
  411. the value inside the `optional`. If the optional is empty (`nothing`), a
  412. compile-time error is triggered. Since we know `%default_` is not empty (we
  413. checked that just above), what we're doing is simply pass the function
  414. associated to the default case to the `process` function. We're now ready
  415. for the final step, which is the implementation of the `process` function:
  416. @snippet example/tutorial/quickstart.switchAny.cpp process
  417. There are two overloads of this function: an overload for when there is at least
  418. one case to process, and the base case overload for when there's only the default
  419. case. As we would expect, the base case simply calls the default function and
  420. returns that result. The other overload is slightly more interesting. First,
  421. we retrieve the type associated to that case and store it in `T`. This
  422. `decltype(...)::%type` dance might seem convoluted, but it is actually quite
  423. simple. Roughly speaking, this takes a type represented as an object (a `type<T>`)
  424. and pulls it back down to the type level (a `T`). The details are explained in
  425. the section on [type-level computations](@ref tutorial-type). Then, we compare
  426. whether the dynamic type of the `any` matches this case, and if so we call the
  427. function associated to this case with the `any` casted to the proper type.
  428. Otherwise, we simply call `process` recursively with the rest of the cases.
  429. Pretty simple, wasn't it? Here's the final solution:
  430. @snippet example/tutorial/quickstart.switchAny.cpp full
  431. That's it for the quick start! This example only introduced a couple of useful
  432. algorithms (`find_if`, `filter`, `unpack`) and heterogeneous containers
  433. (`tuple`, `optional`), but rest assured that there is much more. The next
  434. sections of the tutorial gradually introduce general concepts pertaining to
  435. Hana in a friendly way, but you may use the following cheatsheet for quick
  436. reference if you want to start coding right away. This cheatsheet contains
  437. the most frequently used algorithms and containers, along with a short
  438. description of what each of them does.
  439. @section tutorial-cheatsheet Cheatsheet
  440. ### Remarks
  441. - Most algorithms work on both types and values (see the section on
  442. [type computations](@ref tutorial-type))
  443. - Algorithms always return their result as a new container; no in-place
  444. mutation is ever performed (see the section on [algorithms]
  445. (@ref tutorial-algorithms))
  446. - All algorithms are `constexpr` function objects
  447. container | description
  448. :----------------- | :----------
  449. <code>[tuple](@ref boost::hana::tuple)</code> | General purpose index-based heterogeneous sequence with a fixed length. Use this as a `std::vector` for heterogeneous objects.
  450. <code>[optional](@ref boost::hana::optional)</code> | Represents an optional value, i.e. a value that can be empty. This is a bit like `std::optional`, except that the emptiness is known at compile-time.
  451. <code>[map](@ref boost::hana::map)</code> | Unordered associative array mapping (unique) compile-time entities to arbitrary objects. This is like `std::unordered_map` for heterogeneous objects.
  452. <code>[set](@ref boost::hana::set)</code> | Unordered container holding unique keys that must be compile-time entities. This is like `std::unordered_set` for heterogeneous objects.
  453. <code>[range](@ref boost::hana::range)</code> | Represents an interval of compile-time numbers. This is like `std::integer_sequence`, but better.
  454. <code>[pair](@ref boost::hana::pair)</code> | Container holding two heterogeneous objects. Like `std::pair`, but compresses the storage of empty types.
  455. <code>[string](@ref boost::hana::string)</code> | Compile-time string.
  456. <code>[type](@ref boost::hana::type)</code> | Container representing a C++ type. This is the root of the unification between types and values, and is of interest for MPL-style computations (type-level computations).
  457. <code>[integral_constant](@ref boost::hana::integral_constant)</code> | Represents a compile-time number. This is very similar to `std::integral_constant`, except that `hana::integral_constant` also defines operators and more syntactic sugar.
  458. <code>[lazy](@ref boost::hana::lazy)</code> | Encapsulates a lazy value or computation.
  459. <code>[basic_tuple](@ref boost::hana::basic_tuple)</code> | Stripped-down version of `hana::tuple`. Not standards conforming, but more compile-time efficient.
  460. function | description
  461. :------------------------------------------ | :----------
  462. <code>[adjust](@ref ::boost::hana::adjust)(sequence, value, f)</code> | Apply a function to each element of a sequence that compares equal to some value and return the result.
  463. <code>[adjust_if](@ref ::boost::hana::adjust_if)(sequence, predicate, f)</code> | Apply a function to each element of a sequence satisfying some predicate and return the result.
  464. <code>{[all](@ref ::boost::hana::all),[any](@ref ::boost::hana::any),[none](@ref ::boost::hana::none)}(sequence)</code> | Returns whether all/any/none of the elements of a sequence are true-valued.
  465. <code>{[all](@ref ::boost::hana::all_of),[any](@ref ::boost::hana::any_of),[none](@ref ::boost::hana::none_of)}_of(sequence, predicate)</code> | Returns whether all/any/none of the elements of the sequence satisfy some predicate.
  466. <code>[append](@ref ::boost::hana::append)(sequence, value)</code> | Append an element to a sequence.
  467. <code>[at](@ref ::boost::hana::at)(sequence, index)</code> | Returns the n-th element of a sequence. The index must be an `IntegralConstant`.
  468. <code>[back](@ref ::boost::hana::back)(sequence)</code> | Returns the last element of a non-empty sequence.
  469. <code>[concat](@ref ::boost::hana::concat)(sequence1, sequence2)</code> | Concatenate two sequences.
  470. <code>[contains](@ref ::boost::hana::contains)(sequence, value)</code> | Returns whether a sequence contains the given object.
  471. <code>[count](@ref ::boost::hana::count)(sequence, value)</code> | Returns the number of elements that compare equal to the given value.
  472. <code>[count_if](@ref ::boost::hana::count_if)(sequence, predicate)</code> | Returns the number of elements that satisfy the predicate.
  473. <code>[drop_front](@ref ::boost::hana::drop_front)(sequence[, n])</code> | Drop the first `n` elements from a sequence, or the whole sequence if `length(sequence) <= n`. `n` must be an `IntegralConstant`. When not provided, `n` defaults to 1.
  474. <code>[drop_front_exactly](@ref ::boost::hana::drop_front_exactly)(sequence[, n])</code> | Drop the first `n` elements from a sequence. `n` must be an `IntegralConstant` and the sequence must have at least `n` elements. When not provided, `n` defaults to 1.
  475. <code>[drop_back](@ref ::boost::hana::drop_back)(sequence[, n])</code> | Drop the last `n` elements from a sequence, or the whole sequence if `length(sequence) <= n`. `n` must be an `IntegralConstant`. When not provided, `n` defaults to 1.
  476. <code>[drop_while](@ref ::boost::hana::drop_while)(sequence, predicate)</code> | Drops elements from a sequence while a predicate is satisfied. The predicate must return an `IntegralConstant`.
  477. <code>[fill](@ref ::boost::hana::fill)(sequence, value)</code> | Replace all the elements of a sequence with some value.
  478. <code>[filter](@ref ::boost::hana::filter)(sequence, predicate)</code> | Remove all the elements that do not satisfy a predicate. The predicate must return an `IntegralConstant`.
  479. <code>[find](@ref ::boost::hana::find)(sequence, value)</code> | Find the first element of a sequence which compares equal to some value and return `just` it, or return `nothing`. See `hana::optional`.
  480. <code>[find_if](@ref ::boost::hana::find_if)(sequence, predicate)</code> | Find the first element of a sequence satisfying the predicate and return `just` it, or return `nothing`. See `hana::optional`.
  481. <code>[flatten](@ref ::boost::hana::flatten)(sequence)</code> | Flatten a sequence of sequences, a bit like `std::tuple_cat`.
  482. <code>[fold_left](@ref ::boost::hana::fold_left)(sequence[, state], f)</code> | Accumulates the elements of a sequence from the left, optionally with a provided initial state.
  483. <code>[fold_right](@ref ::boost::hana::fold_right)(sequence[, state], f)</code> | Accumulates the elements of a sequence from the right, optionally with a provided initial state.
  484. <code>[fold](@ref ::boost::hana::fold)(sequence[, state], f)</code> | Equivalent to `fold_left`; provided for consistency with Boost.MPL and Boost.Fusion.
  485. <code>[for_each](@ref ::boost::hana::for_each)(sequence, f)</code> | Call a function on each element of a sequence. Returns `void`.
  486. <code>[front](@ref ::boost::hana::front)(sequence)</code> | Returns the first element of a non-empty sequence.
  487. <code>[group](@ref ::boost::hana::group)(sequence[, predicate])</code> | %Group adjacent elements of a sequence which all satisfy (or all do not satisfy) some predicate. The predicate defaults to equality, in which case the elements must be `Comparable`.
  488. <code>[index_if](@ref ::boost::hana::index_if)(sequence, predicate)</code> | Find the index of the first element in a sequence satisfying the predicate and return `just` it, or return `nothing`. See `hana::optional`.
  489. <code>[insert](@ref ::boost::hana::insert)(sequence, index, element)</code> | Insert an element at a given index. The index must be an `IntegralConstant`.
  490. <code>[insert_range](@ref ::boost::hana::insert_range)(sequence, index, elements)</code> | Insert a sequence of elements at a given index. The index must be an `IntegralConstant`.
  491. <code>[is_empty](@ref ::boost::hana::is_empty)(sequence)</code> | Returns whether a sequence is empty as an `IntegralConstant`.
  492. <code>[length](@ref ::boost::hana::length)(sequence)</code> | Returns the length of a sequence as an `IntegralConstant`.
  493. <code>[lexicographical_compare](@ref ::boost::hana::lexicographical_compare)(sequence1, sequence2[, predicate])</code> | Performs a lexicographical comparison of two sequences, optionally with a custom predicate, by default with `hana::less`.
  494. <code>[maximum](@ref ::boost::hana::maximum)(sequence[, predicate])</code> | Returns the greatest element of a sequence, optionally according to a predicate. The elements must be `Orderable` if no predicate is provided.
  495. <code>[minimum](@ref ::boost::hana::minimum)(sequence[, predicate])</code> | Returns the smallest element of a sequence, optionally according to a predicate. The elements must be `Orderable` if no predicate is provided.
  496. <code>[partition](@ref ::boost::hana::partition)(sequence, predicate)</code> | Partition a sequence into a pair of elements that satisfy some predicate, and elements that do not satisfy it.
  497. <code>[prepend](@ref ::boost::hana::prepend)(sequence, value)</code> | Prepend an element to a sequence.
  498. <code>[remove](@ref ::boost::hana::remove)(sequence, value)</code> | Remove all the elements that are equal to a given value.
  499. <code>[remove_at](@ref ::boost::hana::remove_at)(sequence, index)</code> | Remove the element at the given index. The index must be an `IntegralConstant`.
  500. <code>[remove_if](@ref ::boost::hana::remove_if)(sequence, predicate)</code> | Remove all the elements that satisfy a predicate. The predicate must return an `IntegralConstant`.
  501. <code>[remove_range](@ref ::boost::hana::remove_range)(sequence, from, to)</code> | Remove the elements at indices in the given `[from, to)` half-open interval. The indices must be `IntegralConstant`s.
  502. <code>[replace](@ref ::boost::hana::replace)(sequence, oldval, newval)</code> | Replace the elements of a sequence that compare equal to some value by some other value.
  503. <code>[replace_if](@ref ::boost::hana::replace_if)(sequence, predicate, newval)</code> | Replace the elements of a sequence that satisfy some predicate by some value.
  504. <code>[reverse](@ref ::boost::hana::reverse)(sequence)</code> | Reverse the order of the elements in a sequence.
  505. <code>[reverse_fold](@ref ::boost::hana::reverse_fold)(sequence[, state], f)</code> | Equivalent to `fold_right`; provided for consistency with Boost.MPL and Boost.Fusion.
  506. <code>[size](@ref ::boost::hana::size)(sequence)</code> | Equivalent to `length`; provided for consistency with the C++ standard library.
  507. <code>[slice](@ref ::boost::hana::slice)(sequence, indices)</code> | Returns a new sequence containing the elements at the given indices of the original sequence.
  508. <code>[slice_c](@ref ::boost::hana::slice_c)<from, to>(sequence)</code> | Returns a new sequence containing the elements at indices contained in `[from, to)` of the original sequence.
  509. <code>[sort](@ref ::boost::hana::sort)(sequence[, predicate])</code> | Sort (stably) the elements of a sequence, optionally according to a predicate. The elements must be `Orderable` if no predicate is provided.
  510. <code>[take_back](@ref ::boost::hana::take_back)(sequence, number)</code> | Take the last n elements of a sequence, or the whole sequence if `length(sequence) <= n`. n must be an `IntegralConstant`.
  511. <code>[take_front](@ref ::boost::hana::take_front)(sequence, number)</code> | Take the first n elements of a sequence, or the whole sequence if `length(sequence) <= n`. n must be an `IntegralConstant`.
  512. <code>[take_while](@ref ::boost::hana::take_while)(sequence, predicate)</code> | Take elements of a sequence while some predicate is satisfied, and return that.
  513. <code>[transform](@ref ::boost::hana::transform)(sequence, f)</code> | Apply a function to each element of a sequence and return the result.
  514. <code>[unique](@ref ::boost::hana::unique)(sequence[, predicate])</code> | Removes all consecutive duplicates from a sequence. The predicate defaults to equality, in which case the elements must be `Comparable`.
  515. <code>[unpack](@ref ::boost::hana::unpack)(sequence, f)</code> | Calls a function with the contents of a sequence. Equivalent to `f(x1, ..., xN)`.
  516. <code>[zip](@ref ::boost::hana::zip)(s1, ..., sN)</code> | Zip `N` sequences into a sequence of tuples. All the sequences must have the same length.
  517. <code>[zip_shortest](@ref ::boost::hana::zip_shortest)(s1, ..., sN)</code> | Zip `N` sequences into a sequence of tuples. The resulting sequence has the length of the shortest input sequence.
  518. <code>[zip_with](@ref ::boost::hana::zip_with)(f, s1, ..., sN)</code> | Zip `N` sequences with a `N`-ary function. All the sequences must have the same length.
  519. <code>[zip_shortest_with](@ref ::boost::hana::zip_shortest_with)(f, s1, ..., sN)</code> | Zip `N` sequences with a `N`-ary function. The resulting sequence has the length of the shortest input sequence.
  520. @section tutorial-assert Assertions
  521. ------------------------------------------------------------------------------
  522. In the rest of this tutorial, you will come across code snippets where different
  523. kinds of assertions like `BOOST_HANA_RUNTIME_CHECK` and `BOOST_HANA_CONSTANT_CHECK`
  524. are used. Like any sensible `assert` macro, they basically check that the
  525. condition they are given is satisfied. However, in the context of heterogeneous
  526. programming, some informations are known at compile-time, while others are known
  527. only at runtime. The exact type of assertion that's used in a context tells you
  528. whether the condition that's asserted upon can be known at compile-time or if it
  529. must be computed at runtime, which is a very precious piece of information. Here
  530. are the different kinds of assertions used in the tutorial, with a small
  531. description of their particularities. For more details, you should check
  532. the [reference on assertions](@ref group-assertions).
  533. assertion | description
  534. :--------------------------- | :----------
  535. `BOOST_HANA_RUNTIME_CHECK` | Assertion on a condition that is not known until runtime. This assertion provides the weakest form of guarantee.
  536. `BOOST_HANA_CONSTEXPR_CHECK` | Assertion on a condition that would be `constexpr` if lambdas were allowed inside constant expressions. In other words, the only reason for it not being a `static_assert` is the language limitation that lambdas can't appear in constant expressions, which [might be lifted][N4487] in C++17.
  537. `static_assert` | Assertion on a `constexpr` condition. This is stronger than `BOOST_HANA_CONSTEXPR_CHECK` in that it requires the condition to be a constant expression, and it hence assures that the algorithms used in the expression are `constexpr`-friendly.
  538. `BOOST_HANA_CONSTANT_CHECK` | Assertion on a boolean `IntegralConstant`. This assertion provides the strongest form of guarantee, because an `IntegralConstant` can be converted to a `constexpr` value even if it is not `constexpr` itself.
  539. @section tutorial-integral Compile-time numbers
  540. ------------------------------------------------------------------------------
  541. This section introduces the important notion of `IntegralConstant` and the
  542. philosophy behind Hana's metaprogramming paradigm. Let's start with a rather
  543. odd question. What is an `integral_constant`?
  544. @code{cpp}
  545. template<class T, T v>
  546. struct integral_constant {
  547. static constexpr T value = v;
  548. typedef T value_type;
  549. typedef integral_constant type;
  550. constexpr operator value_type() const noexcept { return value; }
  551. constexpr value_type operator()() const noexcept { return value; }
  552. };
  553. @endcode
  554. @note
  555. If this is totally new to you, you might want to take a look at the
  556. [documentation][C++14.ice] for `std::integral_constant`.
  557. One valid answer is that `integral_constant` represents a type-level
  558. encoding of a number, or more generally any object of an integral type.
  559. For illustration, we could define a successor function on numbers in that
  560. representation very easily by using a template alias:
  561. @code{cpp}
  562. template <typename N>
  563. using succ = integral_constant<int, N::value + 1>;
  564. using one = integral_constant<int, 1>;
  565. using two = succ<one>;
  566. using three = succ<two>;
  567. // ...
  568. @endcode
  569. This is the way `integral_constant`s are usually thought of; as _type-level_
  570. entities that can be used for template metaprogramming. Another way to see
  571. an `integral_constant` is as a runtime object representing a `constexpr` value
  572. of an integral type:
  573. @code{cpp}
  574. auto one = integral_constant<int, 1>{};
  575. @endcode
  576. Here, while `one` is not marked as `constexpr`, the abstract value it holds
  577. (a `constexpr 1`) is still available at compile-time, because that value is
  578. encoded in the type of `one`. Indeed, even if `one` is not `constexpr`, we
  579. can use `decltype` to retrieve the compile-time value it represents:
  580. @code{cpp}
  581. auto one = integral_constant<int, 1>{};
  582. constexpr int one_constexpr = decltype(one)::value;
  583. @endcode
  584. But why on earth would we want to consider `integral_constant`s as objects
  585. instead of type-level entities? To see why, consider how we could now
  586. implement the same successor function as before:
  587. @code{cpp}
  588. template <typename N>
  589. auto succ(N) {
  590. return integral_constant<int, N::value + 1>{};
  591. }
  592. auto one = integral_constant<int, 1>{};
  593. auto two = succ(one);
  594. auto three = succ(two);
  595. // ...
  596. @endcode
  597. Did you notice anything new? The difference is that instead of implementing
  598. `succ` at the type-level with a template alias, we're now implementing it at
  599. the value-level with a template function. Furthermore, we can now perform
  600. compile-time arithmetic using the same syntax as that of normal C++. This
  601. way of seeing compile-time entities as objects instead of types is the key
  602. to Hana's expressive power.
  603. @subsection tutorial-integral-arithmetic Compile-time arithmetic
  604. The MPL defines [arithmetic operators][MPL.arithmetic] that can be used to do
  605. compile-time computations with `integral_constant`s. A typical example of such
  606. an operation is `plus`, which is implemented roughly as:
  607. @code{cpp}
  608. template <typename X, typename Y>
  609. struct plus {
  610. using type = integral_constant<
  611. decltype(X::value + Y::value),
  612. X::value + Y::value
  613. >;
  614. };
  615. using three = plus<integral_constant<int, 1>,
  616. integral_constant<int, 2>>::type;
  617. @endcode
  618. By viewing `integral_constant`s as objects instead of types, the translation
  619. from a metafunction to a function is very straightforward:
  620. @code{cpp}
  621. template <typename V, V v, typename U, U u>
  622. constexpr auto
  623. operator+(integral_constant<V, v>, integral_constant<U, u>)
  624. { return integral_constant<decltype(v + u), v + u>{}; }
  625. auto three = integral_constant<int, 1>{} + integral_constant<int, 2>{};
  626. @endcode
  627. It is very important to emphasize the fact that this operator does not return
  628. a normal integer. Instead, it returns a value-initialized object whose type
  629. contains the result of the addition. The only useful information contained in
  630. that object is actually in its type, and we're creating an object because it
  631. allows us to use this nice value-level syntax. It turns out that we can make
  632. this syntax even better by using a [C++14 variable template][C++14.vtemplate]
  633. to simplify the creation of an `integral_constant`:
  634. @code{cpp}
  635. template <int i>
  636. constexpr integral_constant<int, i> int_c{};
  637. auto three = int_c<1> + int_c<2>;
  638. @endcode
  639. Now we're talking about a visible gain in expressiveness over the initial
  640. type-level approach, aren't we? But there's more; we can also use
  641. [C++14 user defined literals][C++14.udl] to make this process even simpler:
  642. @code{cpp}
  643. template <char ...digits>
  644. constexpr auto operator"" _c() {
  645. // parse the digits and return an integral_constant
  646. }
  647. auto three = 1_c + 2_c;
  648. @endcode
  649. Hana provides its own `integral_constant`s, which define arithmetic operators
  650. just like we showed above. Hana also provides variable templates to easily
  651. create different kinds of `integral_constant`s: `int_c`, `long_c`, `bool_c`,
  652. etc... This allows you to omit the trailing `{}` braces otherwise required to
  653. value-initialize these objects. Of course, the `_c` suffix is also provided;
  654. it is part of the `hana::literals` namespace, and you must import it into
  655. your namespace before using it:
  656. @code{cpp}
  657. using namespace hana::literals;
  658. auto three = 1_c + 2_c;
  659. @endcode
  660. This way, you may do compile-time arithmetic without having to struggle with
  661. awkward type-level idiosyncrasies, and your coworkers will now be able to
  662. understand what's going on.
  663. @subsection tutorial-integral-distance Example: Euclidean distance
  664. To illustrate how good it gets, let's implement a function computing a 2-D
  665. euclidean distance at compile-time. As a reminder, the euclidean distance of
  666. two points in the 2-D plane is given by
  667. @f[
  668. \mathrm{distance}\left((x_1, y_1), (x_2, y_2)\right)
  669. := \sqrt{(x_1 - x_2)^2 + (y_1 - y_2)^2}
  670. @f]
  671. First, here's how it looks like with a type-level approach (using the MPL):
  672. @snippet example/tutorial/integral.cpp distance-mpl
  673. Yeah... Now, let's implement it with the value-level approach presented above:
  674. @snippet example/tutorial/integral.cpp distance-hana
  675. This version looks arguably cleaner. However, this is not all. Notice how the
  676. `distance` function looks exactly as the one you would have written for
  677. computing the euclidean distance on dynamic values? Indeed, because we're
  678. using the same syntax for dynamic and compile-time arithmetic, generic
  679. functions written for one will work for both!
  680. @snippet example/tutorial/integral.cpp distance-dynamic
  681. __Without changing any code__, we can use our `distance` function on runtime
  682. values and everything just works. Now that's DRY.
  683. @subsection tutorial-integral-branching Compile-time branching
  684. Once we have compile-time arithmetic, the next thing that might come to mind
  685. is compile-time branching. When metaprogramming, it is often useful to have
  686. one piece of code be compiled if some condition is true, and a different one
  687. otherwise. If you have heard of [static_if][N4461], this should sound very
  688. familiar, and indeed it is exactly what we are talking about. Otherwise, if
  689. you don't know why we might want to branch at compile-time, consider the
  690. following code (adapted from [N4461][]):
  691. @code{cpp}
  692. template <typename T, typename ...Args>
  693. std::enable_if_t<std::is_constructible<T, Args...>::value,
  694. std::unique_ptr<T>> make_unique(Args&&... args) {
  695. return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
  696. }
  697. template <typename T, typename ...Args>
  698. std::enable_if_t<!std::is_constructible<T, Args...>::value,
  699. std::unique_ptr<T>> make_unique(Args&&... args) {
  700. return std::unique_ptr<T>(new T{std::forward<Args>(args)...});
  701. }
  702. @endcode
  703. This code creates a `std::unique_ptr` using the correct form of syntax for the
  704. constructor. To achieve this, it uses [SFINAE][] and requires two different
  705. overloads. Now, anyone sane seeing this for the first time would ask why it
  706. is not possible to simply write:
  707. @code{cpp}
  708. template <typename T, typename ...Args>
  709. std::unique_ptr<T> make_unique(Args&&... args) {
  710. if (std::is_constructible<T, Args...>::value)
  711. return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
  712. else
  713. return std::unique_ptr<T>(new T{std::forward<Args>(args)...});
  714. }
  715. @endcode
  716. The reason is that the compiler is required to compile both branches of the
  717. `if` statement, regardless of the condition (even though it is known at
  718. compile-time). But when `T` is _not_ constructible from `Args...`, the second
  719. branch will fail to compile, which will cause a hard compilation error. What
  720. we need really is a way to tell the compiler __not to compile__ the second
  721. branch when the condition is true, and the first branch when the condition is
  722. false.
  723. To emulate this, Hana provides an `if_` function that works a bit like a
  724. normal `if` statement, except except it takes a condition that can be an
  725. `IntegralConstant` and returns the one of two values (which may have
  726. different types) chosen by the condition. If the condition is true, the
  727. first value is returned, and otherwise the second value is returned. A
  728. somewhat vain example is the following:
  729. @code{cpp}
  730. auto one_two_three = hana::if_(hana::true_c, 123, "hello");
  731. auto hello = hana::if_(hana::false_c, 123, "hello");
  732. @endcode
  733. @note
  734. `hana::true_c` and `hana::false_c` are just boolean `IntegralConstant`s
  735. representing a compile-time true value and a compile-time false value,
  736. respectively.
  737. Here, `one_two_three` is equal to `123`, and `hello` is equal to `"hello"`.
  738. In other words, `if_` is a little bit like the ternary conditional operator
  739. `? :`, except that both sides of the `:` can have different types:
  740. @code{cpp}
  741. // fails in both cases because both branches have incompatible types
  742. auto one_two_three = hana::true_c ? 123 : "hello";
  743. auto hello = hana::false_c ? 123 : "hello";
  744. @endcode
  745. Ok, so this is neat, but how can it actually help us write complete branches
  746. that are lazily instantiated by the compiler? The answer is to represent both
  747. branches of the `if` statement we'd like to write as generic lambdas, and to
  748. use `hana::if_` to return the branch that we'd like to execute. Here's how we
  749. could rewrite `make_unique`:
  750. @snippet example/tutorial/integral-branching.cpp make_unique.if_
  751. Here, the first value given to `hana::if_` is a generic lambda representing
  752. the branch we want to execute if the condition is true, and the second value
  753. is the branch we want to execute otherwise. `hana::if_` simply returns the
  754. branch chosen by the condition, and we call that branch (which is a generic
  755. lambda) immediately with `std::forward<Args>(args)...`. Hence, the proper
  756. generic lambda ends up being called, with `x...` being `args...`, and we
  757. return the result of that call.
  758. The reason why this approach works is because the body of each branch can only
  759. be instantiated when the types of all `x...` are known. Indeed, since the
  760. branch is a generic lambda, the type of the argument is not known until the
  761. lambda is called, and the compiler must wait for the types of `x...` to be
  762. known before type-checking the lambda's body. Since the erroneous lambda is
  763. never called when the condition is not satisfied (`hana::if_` takes care of
  764. that), the body of the lambda that would fail is never type-checked and no
  765. compilation error happens.
  766. @note
  767. The branches inside the `if_` are lambdas. As such, they really are different
  768. functions from the `make_unique` function. The variables appearing inside
  769. those branches have to be either captured by the lambdas or passed to them as
  770. arguments, and so they are affected by the way they are captured or passed
  771. (by value, by reference, etc..).
  772. Since this pattern of expressing branches as lambdas and then calling them
  773. is very common, Hana provides a `eval_if` function whose purpose is to make
  774. compile-time branching easier. `eval_if` comes from the fact that in a lambda,
  775. one can either receive input data as arguments or capture it from the context.
  776. However, for the purpose of emulating a language level `if` statement,
  777. implicitly capturing variables from the enclosing scope is usually more
  778. natural. Hence, what we would prefer writing is
  779. @code{cpp}
  780. template <typename T, typename ...Args>
  781. std::unique_ptr<T> make_unique(Args&&... args) {
  782. return hana::if_(std::is_constructible<T, Args...>{},
  783. [&] { return std::unique_ptr<T>(new T(std::forward<Args>(args)...)); },
  784. [&] { return std::unique_ptr<T>(new T{std::forward<Args>(args)...}); }
  785. );
  786. }
  787. @endcode
  788. Here, we're capturing the `args...` variables from the enclosing scope, which
  789. prevents us from having to introduce the new `x...` variables and passing them
  790. as arguments to the branches. However, this has two problems. First, this will
  791. not achieve the right result, since `hana::if_` will end up returning a lambda
  792. instead of returning the result of calling that lambda. To fix this, we can use
  793. `hana::eval_if` instead of `hana::if_`:
  794. @code{cpp}
  795. template <typename T, typename ...Args>
  796. std::unique_ptr<T> make_unique(Args&&... args) {
  797. return hana::eval_if(std::is_constructible<T, Args...>{},
  798. [&] { return std::unique_ptr<T>(new T(std::forward<Args>(args)...)); },
  799. [&] { return std::unique_ptr<T>(new T{std::forward<Args>(args)...}); }
  800. );
  801. }
  802. @endcode
  803. Here, we capture the enclosing `args...` by reference using `[&]`, and we do
  804. not need to receive any arguments. Also, `hana::eval_if` assumes that its
  805. arguments are branches that can be called, and it will take care of calling
  806. the branch that is selected by the condition. However, this will still cause
  807. a compilation failure, because the bodies of the lambdas are not dependent
  808. anymore, and semantic analysis will be done for both branches even though
  809. only one would end up being used. The solution to this problem is to make
  810. the bodies of the lambdas artificially dependent on something, to prevent the
  811. compiler from being able to perform semantic analysis before the lambda is
  812. actually used. To make this possible, `hana::eval_if` will call the selected
  813. branch with an identity function (a function that returns its argument
  814. unchanged), if the branch accepts such an argument:
  815. @snippet example/tutorial/integral-branching.cpp make_unique.eval_if
  816. Here, the bodies of the branches take an additional argument called `_` by
  817. convention. This argument will be provided by `hana::eval_if` to the branch
  818. that was selected. Then, we use `_` as a function on the variables that we
  819. want to make dependent within the body of each branch. What happens is that
  820. `_` will always be a function that returns its argument unchanged. However,
  821. the compiler can't possibly know it before the lambda has actually been called,
  822. so it can't know the type of `_(args)`. This prevents the compiler from being
  823. able to perform semantic analysis, and no compilation error happens. Plus,
  824. since `_(x)` is guaranteed to be equivalent to `x`, we know that we're not
  825. actually changing the semantics of the branches by using this trick.
  826. While using this trick may seem cumbersome, it can be very useful when dealing
  827. with many variables inside a branch. Furthermore, it is not required to wrap
  828. all variables with `_`; only variables that are involved in an expression whose
  829. type-checking has to be delayed must be wrapped, but the other ones are not
  830. required. There are still a few things to know about compile-time branching
  831. in Hana, but you can dig deeper by looking at the reference for `hana::eval_if`,
  832. `hana::if_` and `hana::lazy`.
  833. @subsection tutorial-integral-more Why stop here?
  834. Why should we limit ourselves to arithmetic operations and branching? When you
  835. start considering `IntegralConstant`s as objects, it becomes sensible to augment
  836. their interface with more functions that are generally useful. For example,
  837. Hana's `IntegralConstant`s define a `times` member function that can be used
  838. to invoke a function a certain number of times, which is especially useful
  839. for loop unrolling:
  840. @code{cpp}
  841. __attribute__((noinline)) void f() { }
  842. int main() {
  843. hana::int_c<10>.times(f);
  844. }
  845. @endcode
  846. In the above code, the 10 calls to `f` are expanded at compile-time. In other
  847. words, this is equivalent to writing
  848. @code{cpp}
  849. f(); f(); ... f(); // 10 times
  850. @endcode
  851. @note
  852. Always [be careful][Chandler.MeetingC++] about manually unrolling loops or
  853. doing other such optimizations manually. In most cases, your compiler is
  854. probably better than you at optimizing. When in doubt, benchmark.
  855. Another nice use of `IntegralConstant`s is to define good-looking operators
  856. for indexing heterogeneous sequences. Whereas `std::tuple` must be accessed
  857. with `std::get`, `hana::tuple` can be accessed using the familiar `operator[]`
  858. used for standard library containers:
  859. @code{cpp}
  860. auto values = hana::make_tuple(1, 'x', 3.4f);
  861. char x = values[1_c];
  862. @endcode
  863. How this works is very simple. Basically, `hana::tuple` defines an `operator[]`
  864. taking an `IntegralConstant` instead of a normal integer, in a way similar to
  865. @code{cpp}
  866. template <typename N>
  867. constexpr decltype(auto) operator[](N const&) {
  868. return std::get<N::value>(*this);
  869. }
  870. @endcode
  871. This is the end of the section on `IntegralConstant`s. This section introduced
  872. the feel behind Hana's new way of metaprogramming; if you liked what you've
  873. seen so far, the rest of this tutorial should feel just like home.
  874. @section tutorial-type Type computations
  875. ------------------------------------------------------------------------------
  876. At this point, if you are interested in doing type-level computations as with
  877. the MPL, you might be wondering how is Hana going to help you. Do not despair.
  878. Hana provides a way to perform type-level computations with a great deal of
  879. expressiveness by representing types as values, just like we represented
  880. compile-time numbers as values. This is a completely new way of approaching
  881. metaprogramming, and you should try to set your old MPL habits aside for a bit
  882. if you want to become proficient with Hana.
  883. However, please be aware that modern C++ features like [auto-deduced return type]
  884. [C++14.auto_rt] remove the need for type computations in many cases. Hence,
  885. before even considering to do a type computation, you should ask yourself
  886. whether there's a simpler way to achieve what you're trying to achieve. In
  887. most cases, the answer will be yes. However, when the answer is no, Hana will
  888. provide you with nuclear-strength facilities to do what needs to be done.
  889. @subsection tutorial-type-objects Types as objects
  890. The key behind Hana's approach to type-level computations is essentially the
  891. same as the approach to compile-time arithmetic. Basically, the idea is to
  892. represent compile-time entities as objects by wrapping them into some kind of
  893. container. For `IntegralConstant`s, the compile-time entities were constant
  894. expressions of an integral type and the wrapper we used was `integral_constant`.
  895. In this section, the compile-time entities will be types and the wrapper we'll
  896. be using is called `type`. Just like we did for `IntegralConstant`s, let's
  897. start by defining a dummy template that could be used to represent a type:
  898. @code{cpp}
  899. template <typename T>
  900. struct basic_type {
  901. // empty (for now)
  902. };
  903. basic_type<int> Int{};
  904. basic_type<char> Char{};
  905. // ...
  906. @endcode
  907. @note
  908. We're using the name `basic_type` here because we're only building a naive
  909. version of the actual functionality provided by Hana.
  910. While this may seem completely useless, it is actually enough to start writing
  911. metafunctions that look like functions. Indeed, consider the following
  912. alternate implementations of `std::add_pointer` and `std::is_pointer`:
  913. @code{cpp}
  914. template <typename T>
  915. constexpr basic_type<T*> add_pointer(basic_type<T> const&)
  916. { return {}; }
  917. template <typename T>
  918. constexpr auto is_pointer(basic_type<T> const&)
  919. { return hana::bool_c<false>; }
  920. template <typename T>
  921. constexpr auto is_pointer(basic_type<T*> const&)
  922. { return hana::bool_c<true>; }
  923. @endcode
  924. We've just written metafunctions that look like functions, just like we wrote
  925. compile-time arithmetic metafunctions as heterogeneous C++ operators in the
  926. previous section. Here's how we can use them:
  927. @code{cpp}
  928. basic_type<int> t{};
  929. auto p = add_pointer(t);
  930. BOOST_HANA_CONSTANT_CHECK(is_pointer(p));
  931. @endcode
  932. Notice how we can now use a normal function call syntax to perform type-level
  933. computations? This is analogous to how using values for compile-time numbers
  934. allowed us to use normal C++ operators to perform compile-time computations.
  935. Like we did for `integral_constant`, we can also go one step further and use
  936. C++14 variable templates to provide syntactic sugar for creating types:
  937. @code{cpp}
  938. template <typename T>
  939. constexpr basic_type<T> type_c{};
  940. auto t = type_c<int>;
  941. auto p = add_pointer(t);
  942. BOOST_HANA_CONSTANT_CHECK(is_pointer(p));
  943. @endcode
  944. @note
  945. This is not exactly how the `hana::type_c` variable template is implemented
  946. because of some subtleties; things were dumbed down here for the sake of the
  947. explanation. Please check the reference for `hana::type` to know exactly
  948. what you can expect from a `hana::type_c<...>`.
  949. @subsection tutorial-type-benefits Benefits of this representation
  950. But what does that buy us? Well, since a `type_c<...>` is just an object, we
  951. can store it in a heterogeneous sequence like a tuple, we can move it around
  952. and pass it to (or return it from) functions, and we can do basically anything
  953. else that requires an object:
  954. @snippet example/tutorial/type.cpp tuple
  955. @note
  956. Writing `make_tuple(type_c<T>...)` can be annoying when there are several types.
  957. For this reason, Hana provides the `tuple_t<T...>` variable template, which is
  958. syntactic sugar for `make_tuple(type_c<T>...)`.
  959. Also, notice that since the above tuple is really just a normal heterogeneous
  960. sequence, we can apply heterogeneous algorithms on that sequence just like we
  961. could on a tuple of `int`s, for example. Furthermore, since we're just
  962. manipulating objects, we can now use the full language instead of just the
  963. small subset available at the type-level. For example, consider the task of
  964. removing all the types that are not a reference or a pointer from a sequence
  965. of types. With the MPL, we would have to use a placeholder expression to
  966. express the predicate, which is clunky:
  967. @snippet example/tutorial/type.cpp filter.MPL
  968. Now, since we're manipulating objects, we can use the full language and use a
  969. generic lambda instead, which leads to much more readable code:
  970. @snippet example/tutorial/type.cpp filter.Hana
  971. Since Hana handles all heterogeneous containers uniformly, this approach of
  972. representing types as values also has the benefit that a single library is
  973. now needed for both heterogeneous computations and type level computations.
  974. Indeed, whereas we would normally need two different libraries to perform
  975. almost identical tasks, we now need a single library. Again, consider the
  976. task of filtering a sequence with a predicate. With MPL and Fusion, this
  977. is what we must do:
  978. @snippet example/tutorial/type.cpp single_library.then
  979. With Hana, a single library is required. Notice how we use the same `filter`
  980. algorithm and the same container, and only tweak the predicate so it can
  981. operate on values:
  982. @snippet example/tutorial/type.cpp single_library.Hana
  983. But that is not all. Indeed, having a unified syntax for type-level and
  984. value-level computations allows us to achieve greater consistency in the
  985. interface of heterogeneous containers. For example, consider the simple
  986. task of creating a heterogeneous map associating types to values, and then
  987. accessing an element of it. With Fusion, what's happening is far from obvious
  988. to the untrained eye:
  989. @snippet example/tutorial/type.cpp make_map.Fusion
  990. However, with a unified syntax for types and values, the same thing becomes
  991. much clearer:
  992. @snippet example/tutorial/type.cpp make_map.Hana
  993. While Hana's way takes more lines of codes, it is also arguably more readable
  994. and closer to how someone would expect to initialize a map.
  995. @subsection tutorial-type-working Working with this representation
  996. So far, we can represent types as values and perform type-level computations
  997. on those objects using the usual C++ syntax. This is nice, but it is not very
  998. useful because we have no way to get back a normal C++ type from an object
  999. representation. For example, how could we declare a variable whose type is the
  1000. result of a type computation?
  1001. @code{cpp}
  1002. auto t = add_pointer(hana::type_c<int>); // could be a complex type computation
  1003. using T = the-type-represented-by-t;
  1004. T var = ...;
  1005. @endcode
  1006. Right now, there is no easy way to do it. To make this easier to achieve, we
  1007. enrich the interface of the `basic_type` container that we defined above.
  1008. Instead of being an empty `struct`, we now define it as
  1009. @code{cpp}
  1010. template <typename T>
  1011. struct basic_type {
  1012. using type = T;
  1013. };
  1014. @endcode
  1015. @note
  1016. This is equivalent to making `basic_type` a metafunction in the MPL sense.
  1017. This way, we can use `decltype` to easily access the actual C++ type
  1018. represented by a `type_c<...>` object:
  1019. @code{cpp}
  1020. auto t = add_pointer(hana::type_c<int>);
  1021. using T = decltype(t)::type; // fetches basic_type<T>::type
  1022. T var = ...;
  1023. @endcode
  1024. In general, doing type-level metaprogramming with Hana is a three step process:
  1025. 1. Represent types as objects by wrapping them with `hana::type_c<...>`
  1026. 2. Perform type transformations with value syntax
  1027. 3. Unwrap the result with `decltype(...)::%type`
  1028. Now, you must be thinking that this is incredibly cumbersome. In reality, it
  1029. is very manageable for several reasons. First, this wrapping and unwrapping
  1030. only needs to happen at some very thin boundaries.
  1031. @code{cpp}
  1032. auto t = hana::type_c<T>;
  1033. auto result = huge_type_computation(t);
  1034. using Result = decltype(result)::type;
  1035. @endcode
  1036. Furthermore, since you get the advantage of working with objects (without
  1037. having to wrap/unwrap) inside the computation, the cost of wrapping and
  1038. unwrapping is amortized on the whole computation. Hence, for complex type
  1039. computations, the syntactic noise of this three step process quickly becomes
  1040. negligible in light of the expressiveness gain of working with values inside
  1041. that computation. Also, using values instead of types means that we can avoid
  1042. typing `typename` and `template` all around the place, which accounted for a
  1043. lot of syntactic noise in classic metaprogramming.
  1044. Another point is that the three full steps are not always required. Indeed,
  1045. sometimes one just needs to do a type-level computation and query something
  1046. about the result, without necessarily fetching the result as a normal C++ type:
  1047. @code{cpp}
  1048. auto t = hana::type_c<T>;
  1049. auto result = type_computation(t);
  1050. BOOST_HANA_CONSTANT_CHECK(is_pointer(result)); // third step skipped
  1051. @endcode
  1052. In this case, we were able to skip the third step because we did not need to
  1053. access the actual type represented by `result`. In other cases, the first step
  1054. can be avoided, like when using `tuple_t`, which has no more syntactic noise
  1055. than any other pure type-level approach:
  1056. @snippet example/tutorial/type.cpp skip_first_step
  1057. For skeptical readers, let's consider the task of finding the smallest type
  1058. in a sequence of types. This is a very good example of a short type-only
  1059. computation, which is where we would expect the new paradigm to suffer the
  1060. most. As you will see, things stay manageable even for small computations.
  1061. First, let's implement it with the MPL:
  1062. @snippet example/tutorial/type.cpp smallest.MPL
  1063. The result is quite readable (for anyone familiar with the MPL). Let's now
  1064. implement the same thing using Hana:
  1065. @snippet example/tutorial/type.cpp smallest.Hana
  1066. As you can witness, the syntactic noise of the 3-step process is almost
  1067. completely hidden by the rest of the computation.
  1068. @subsection tutorial-type-lifting The generic lifting process
  1069. The first type-level computation that we introduced in the form of a function
  1070. looked like:
  1071. @code{cpp}
  1072. template <typename T>
  1073. constexpr auto add_pointer(hana::basic_type<T> const&) {
  1074. return hana::type_c<T*>;
  1075. }
  1076. @endcode
  1077. While it looks more complicated, we could also write it as:
  1078. @code{cpp}
  1079. template <typename T>
  1080. constexpr auto add_pointer(hana::basic_type<T> const&) {
  1081. return hana::type_c<typename std::add_pointer<T>::type>;
  1082. }
  1083. @endcode
  1084. However, this implementation emphasizes the fact that we're really emulating
  1085. an existing metafunction and simply representing it as a function. In other
  1086. words, we're _lifting_ a metafunction (`std::add_pointer`) to the world of
  1087. values by creating our own `add_pointer` function. It turns out that this
  1088. lifting process is a generic one. Indeed, given any metafunction, we could
  1089. write almost the same thing:
  1090. @code{cpp}
  1091. template <typename T>
  1092. constexpr auto add_const(hana::basic_type<T> const&)
  1093. { return hana::type_c<typename std::add_const<T>::type>; }
  1094. template <typename T>
  1095. constexpr auto add_volatile(hana::basic_type<T> const&)
  1096. { return hana::type_c<typename std::add_volatile<T>::type>; }
  1097. template <typename T>
  1098. constexpr auto add_lvalue_reference(hana::basic_type<T> const&)
  1099. { return hana::type_c<typename std::add_lvalue_reference<T>::type>; }
  1100. // etc...
  1101. @endcode
  1102. This mechanical transformation is easy to abstract into a generic lifter
  1103. that can handle any [MPL Metafunction][MPL.metafunction] as follows:
  1104. @snippet example/tutorial/type.cpp metafunction1
  1105. More generally, we'll want to allow metafunctions with any number of
  1106. arguments, which brings us to the following less naive implementation:
  1107. @snippet example/tutorial/type.cpp metafunction2
  1108. Hana provides a similar generic metafunction lifter called `hana::metafunction`.
  1109. One small improvement is that `hana::metafunction<F>` is a function object
  1110. instead of an overloaded function, so one can pass it to higher-order
  1111. algorithms. It is also a model of the slightly more powerful concept of
  1112. `Metafunction`, but this can safely be ignored for now. The process we
  1113. explored in this section does not only apply to metafunctions; it also
  1114. applies to templates. Indeed, we could define:
  1115. @snippet example/tutorial/type.cpp template_
  1116. Hana provides a generic lifter for templates named `hana::template_`, and it
  1117. also provides a generic lifter for [MPL MetafunctionClasses][MPL.mfc] named
  1118. `hana::metafunction_class`. This gives us a way to uniformly represent "legacy"
  1119. type-level computations as functions, so that any code written using a classic
  1120. type-level metaprogramming library can almost trivially be used with Hana. For
  1121. example, say you have a large chunk of MPL-based code and you'd like to
  1122. interface with Hana. The process of doing so is no harder than wrapping your
  1123. metafunctions with the lifter provided by Hana:
  1124. @code{cpp}
  1125. template <typename T>
  1126. struct legacy {
  1127. using type = ...; // something you really don't want to mess with
  1128. };
  1129. auto types = hana::make_tuple(...);
  1130. auto use = hana::transform(types, hana::metafunction<legacy>);
  1131. @endcode
  1132. However, note that not all type-level computations can be lifted as-is with
  1133. the tools provided by Hana. For example, `std::extent` can't be lifted because
  1134. it requires non-type template parameters. Since there is no way to deal with
  1135. non-type template parameters uniformly in C++, one must resort to using a
  1136. hand-written function object specific to that type-level computation:
  1137. @snippet example/tutorial/type.cpp extent
  1138. @note
  1139. Do not forget to include the bridge header for `std::integral_constant`s
  1140. (`<boost/hana/ext/std/integral_constant.hpp>`) when using type traits from
  1141. `<type_traits>` directly.
  1142. In practice, however, this should not be a problem since the vast majority
  1143. of type-level computations can be lifted easily. Finally, since metafunctions
  1144. provided by the `<type_traits>` header are used so frequently, Hana provides
  1145. a lifted version for every one of them. Those lifted traits are in the
  1146. `hana::traits` namespace, and they live in the `<boost/hana/traits.hpp>` header:
  1147. @snippet example/tutorial/type.cpp traits
  1148. This is the end of the section on type computations. While this new paradigm
  1149. for type level programming might be difficult to grok at first, it will make
  1150. more sense as you use it more and more. You will also come to appreciate how
  1151. it blurs the line between types and values, opening new exciting possibilities
  1152. and simplifying many tasks.
  1153. @note
  1154. Curious or skeptical readers should consider checking the minimal
  1155. reimplementation of the MPL presented in the appendices.
  1156. @section tutorial-introspection Introspection
  1157. ------------------------------------------------------------------------------
  1158. Static introspection, as we will discuss it here, is the ability of a program
  1159. to examine the type of an object at compile-time. In other words, it is a
  1160. programmatic interface to interact with types at compile-time. For example,
  1161. have you ever wanted to check whether some unknown type has a member named
  1162. `foo`? Or perhaps at some point you have needed to iterate on the members
  1163. of a `struct`?
  1164. @code{cpp}
  1165. struct Person {
  1166. std::string name;
  1167. int age;
  1168. };
  1169. Person john{"John", 30};
  1170. for (auto& member : john)
  1171. std::cout << member.name << ": " << member.value << std::endl;
  1172. // name: John
  1173. // age: 30
  1174. @endcode
  1175. If you have written a bit of templates in your life, chances are very high
  1176. that you came across the first problem of checking for a member. Also, anyone
  1177. having tried to implement object serialization or even just pretty printing
  1178. has come across the second problem. In most dynamic languages like Python,
  1179. Ruby or JavaScript, these problems are completely solved and introspection is
  1180. used every day by programmers to make a lot of tasks simpler. However, as a
  1181. C++ programmer, we do not have language support for those things, which makes
  1182. several tasks much harder than they should be. While language support would
  1183. likely be needed to properly tackle this problem, Hana makes some common
  1184. introspection patterns much more accessible.
  1185. @subsection tutorial-introspection-is_valid Checking expression validity
  1186. Given an object of an unknown type, it is sometimes desirable to check
  1187. whether this object has a member (or member function) with some name.
  1188. This can be used to perform sophisticated flavors of overloading. For
  1189. example, consider the problem of calling a `toString` method on objects
  1190. that support it, but providing another default implementation for objects
  1191. that do not support it:
  1192. @code{cpp}
  1193. template <typename T>
  1194. std::string optionalToString(T const& obj) {
  1195. if (obj.toString() is a valid expression)
  1196. return obj.toString();
  1197. else
  1198. return "toString not defined";
  1199. }
  1200. @endcode
  1201. @note
  1202. While most use cases for this technique will be addressed by [concepts lite]
  1203. [C++17.clite] in future revisions of the standard, there will still be cases
  1204. where a quick and dirty check is more convenient than creating a full blown
  1205. concept.
  1206. How could we implement a check for the validity of `obj.toString()` as above
  1207. in a generic fashion (so it can be reused in other functions, for example)?
  1208. Normally, we would be stuck writing some kind of SFINAE-based detection:
  1209. @snippet example/tutorial/introspection.cpp has_toString.then
  1210. This works, but the intent is not very clear and most people without a deep
  1211. knowledge of template metaprogramming would think this is black magic. Then,
  1212. we could implement `optionalToString` as
  1213. @code{cpp}
  1214. template <typename T>
  1215. std::string optionalToString(T const& obj) {
  1216. if (has_toString<T>::value)
  1217. return obj.toString();
  1218. else
  1219. return "toString not defined";
  1220. }
  1221. @endcode
  1222. @note
  1223. Of course, this implementation won't actually work because both branches of
  1224. the `if` statement will be compiled. If `obj` does not have a `toString`
  1225. method, the compilation of the `if` branch will fail. We will address
  1226. this issue in a moment.
  1227. Instead of the above SFINAE trick, Hana provides a `is_valid` function that
  1228. can be combined with [C++14 generic lambdas][C++14.glambda] to obtain a much
  1229. cleaner implementation of the same thing:
  1230. @snippet example/tutorial/introspection.cpp has_toString.now
  1231. This leaves us with a function object `has_toString` which returns whether the
  1232. given expression is valid on the argument we pass to it. The result is returned
  1233. as an `IntegralConstant`, so `constexpr`-ness is not an issue here because the
  1234. result of the function is represented as a type anyway. Now, in addition to
  1235. being less verbose (that's a one liner!), the intent is much clearer. Other
  1236. benefits are the fact that `has_toString` can be passed to higher order
  1237. algorithms and it can also be defined at function scope, so there is no need
  1238. to pollute the namespace scope with implementation details. Here is how we
  1239. would now write `optionalToString`:
  1240. @code{cpp}
  1241. template <typename T>
  1242. std::string optionalToString(T const& obj) {
  1243. if (has_toString(obj))
  1244. return obj.toString();
  1245. else
  1246. return "toString not defined";
  1247. }
  1248. @endcode
  1249. Much cleaner, right? However, as we said earlier, this implementation won't
  1250. actually work because both branches of the `if` always have to be compiled,
  1251. regardless of whether `obj` has a `toString` method. There are several
  1252. possible options, but the most classical one is to use `std::enable_if`:
  1253. @snippet example/tutorial/introspection.cpp optionalToString.then
  1254. @note
  1255. We're using the fact that `has_toString` returns an `IntegralConstant` to
  1256. write `decltype(...)::%value`, which is a constant expression. For some
  1257. reason, `has_toString(obj)` is not considered a constant expression, even
  1258. though I think it should be one because we never read from `obj` (see the
  1259. section on [advanced constexpr](@ref tutorial-appendix-constexpr)).
  1260. While this implementation is perfectly valid, it is still pretty cumbersome
  1261. because it requires writing two different functions and going through the
  1262. hoops of SFINAE explicitly by using `std::enable_if`. However, as you might
  1263. remember from the section on [compile-time branching](@ref tutorial-integral-branching),
  1264. Hana provides an `if_` function that can be used to emulate the functionality
  1265. of [static_if][N4461]. Here is how we could write `optionalToString` with
  1266. `hana::if_`:
  1267. @snippet example/tutorial/introspection.cpp optionalToString
  1268. Now, the previous example covered only the specific case of checking for the
  1269. presence of a non-static member function. However, `is_valid` can be used to
  1270. detect the validity of almost any kind of expression. For completeness, we
  1271. now present a list of common use cases for validity checking along with how
  1272. to use `is_valid` to implement them.
  1273. @subsubsection tutorial-introspection-is_valid-non_static Non-static members
  1274. The first idiom we'll look at is checking for the presence of a non-static
  1275. member. We can do it in a similar way as we did for the previous example:
  1276. @snippet example/tutorial/introspection.cpp non_static_member_from_object
  1277. Notice how we cast the result of `x.member` to `void`? This is to make sure
  1278. that our detection also works for types that can't be returned from functions,
  1279. like array types. Also, it is important to use a reference as the parameter to
  1280. our generic lambda, because that would otherwise require `x` to be
  1281. [CopyConstructible][], which is not what we're trying to check. This approach
  1282. is simple and the most convenient when an object is available. However, when
  1283. the checker is intended to be used with no object around, the following
  1284. alternate implementation can be better suited:
  1285. @snippet example/tutorial/introspection.cpp non_static_member_from_type
  1286. This validity checker is different from what we saw earlier because the
  1287. generic lambda is not expecting an usual object anymore; it is now expecting
  1288. a `type` (which is an object, but still represents a type). We then use the
  1289. `hana::traits::declval` _lifted metafunction_ from the `<boost/hana/traits.hpp>`
  1290. header to create an rvalue of the type represented by `t`, which we can then
  1291. use to check for a non-static member. Finally, instead of passing an actual
  1292. object to `has_member` (like `Foo{}` or `Bar{}`), we now pass a `type_c<...>`.
  1293. This implementation is ideal for when no object is lying around.
  1294. @subsubsection tutorial-introspection-is_valid-static Static members
  1295. Checking for a static member is easy, and it is provided for completeness:
  1296. @snippet example/tutorial/introspection.cpp static_member
  1297. Again, we expect a `type` to be passed to the checker. Inside the generic
  1298. lambda, we use `decltype(t)::%type` to fetch the actual C++ type represented
  1299. by the `t` object, as explained in the section on [type computations]
  1300. (@ref tutorial-type-working). Then, we fetch the static member inside
  1301. that type and cast it to `void`, for the same reason as we did for non-static
  1302. members.
  1303. @subsubsection tutorial-introspection-is_valid-nested-typename Nested type names
  1304. Checking for a nested type name is not hard, but it is slightly more
  1305. convoluted than the previous cases:
  1306. @snippet example/tutorial/introspection.cpp nested_type_name
  1307. One might wonder why we use `-> hana::type<typename-expression>` instead
  1308. of simply `-> typename-expression`. Again, the reason is that we want to
  1309. support types that can't be returned from functions, like array types or
  1310. incomplete types.
  1311. @subsubsection tutorial-introspection-is_valid-nested-template Nested templates
  1312. Checking for a nested template name is similar to checking for a nested type
  1313. name, except we use the `template_<...>` variable template instead of
  1314. `type<...>` in the generic lambda:
  1315. @snippet example/tutorial/introspection.cpp nested_template
  1316. @subsubsection tutorial-introspection-is_valid-template Template specializations
  1317. Checking whether a template specialization is valid can be done too, but we
  1318. now pass a `template_<...>` to `is_valid` instead of a `type<...>`, because
  1319. that's what we want to make the check on:
  1320. @snippet example/tutorial/introspection.cpp template_specialization
  1321. @note
  1322. Doing this will not cause the template to be instantiated. Hence, it will only
  1323. check whether the given template can be mentioned with the provided template
  1324. arguments, not whether the instantiation of the template with those arguments
  1325. is valid. Generally speaking, there is no way to check that programmatically.
  1326. @subsection tutorial-introspection-sfinae Taking control of SFINAE
  1327. Doing something only if an expression is well-formed is a very common pattern
  1328. in C++. Indeed, the `optionalToString` function is just one instance of the
  1329. following pattern, which is very general:
  1330. @code{cpp}
  1331. template <typename T>
  1332. auto f(T x) {
  1333. if (some expression involving x is well-formed)
  1334. return something involving x;
  1335. else
  1336. return something else;
  1337. }
  1338. @endcode
  1339. To encapsulate this pattern, Hana provides the `sfinae` function, which allows
  1340. executing an expression, but only if it is well-formed:
  1341. @snippet example/tutorial/introspection.sfinae.cpp maybe_add
  1342. Here, we create a `maybe_add` function, which is simply a generic lambda
  1343. wrapped with Hana's `sfinae` function. `maybe_add` is a function which takes
  1344. two inputs and returns `just` the result of the generic lambda if that call
  1345. is well-formed, and `nothing` otherwise. `just(...)` and `nothing` both belong
  1346. to a type of container called `hana::optional`, which is essentially a
  1347. compile-time `std::optional`. All in all, `maybe_add` is morally equivalent
  1348. to the following function returning a `std::optional`, except that the check
  1349. is done at compile-time:
  1350. @code{cpp}
  1351. auto maybe_add = [](auto x, auto y) {
  1352. if (x + y is well formed)
  1353. return std::optional<decltype(x + y)>{x + y};
  1354. else
  1355. return std::optional<???>{};
  1356. };
  1357. @endcode
  1358. It turns out that we can take advantage of `sfinae` and `optional` to
  1359. implement the `optionalToString` function as follows:
  1360. @snippet example/tutorial/introspection.sfinae.cpp optionalToString.sfinae
  1361. First, we wrap `toString` with the `sfinae` function. Hence, `maybe_toString`
  1362. is a function which either returns `just(x.toString())` if that is well-formed,
  1363. or `nothing` otherwise. Secondly, we use the `.value_or()` function to extract
  1364. the optional value from the container. If the optional value is `nothing`,
  1365. `.value_or()` returns the default value given to it; otherwise, it returns the
  1366. value inside the `just` (here `x.toString()`). This way of seeing SFINAE as a
  1367. special case of computations that might fail is very clean and powerful,
  1368. especially since `sfinae`'d functions can be combined through the
  1369. `hana::optional` `Monad`, which is left to the reference documentation.
  1370. @subsection tutorial-introspection-adapting Introspecting user-defined types
  1371. Have you ever wanted to iterate over the members of a user-defined type? The
  1372. goal of this section is to show you how Hana can be used to do it quite easily.
  1373. To allow working with user-defined types, Hana defines the `Struct` concept.
  1374. Once a user-defined type is a model of that concept, one can iterate over the
  1375. members of an object of that type and query other useful information. To turn
  1376. a user-defined type into a `Struct`, a couple of options are available. First,
  1377. you may define the members of your user-defined type with the
  1378. `BOOST_HANA_DEFINE_STRUCT` macro:
  1379. @snippet example/tutorial/introspection.adapt.cpp BOOST_HANA_DEFINE_STRUCT
  1380. This macro defines two members (`name` and `age`) with the given types. Then,
  1381. it defines some boilerplate inside a `Person::hana` nested `struct`, which is
  1382. required to make `Person` a model of the `Struct` concept. No constructors are
  1383. defined (so [POD-ness][POD] is retained), the members are defined in the same
  1384. order as they appear here and the macro can be used with template `struct`s
  1385. just as well, and at any scope. Also note that you are free to add more
  1386. members to the `Person` type after or before you use the macro. However,
  1387. only members defined with the macro will be picked up when introspecting the
  1388. `Person` type. Easy enough? Now, a `Person` can be accessed programmatically:
  1389. @snippet example/tutorial/introspection.adapt.cpp for_each
  1390. Iteration over a `Struct` is done as if the `Struct` was a sequence of pairs,
  1391. where the first element of a pair is the key associated to a member, and the
  1392. second element is the member itself. When a `Struct` is defined through the
  1393. `BOOST_HANA_DEFINE_STRUCT` macro, the key associated to any member is a
  1394. compile-time `hana::string` representing the name of that member. This is why
  1395. the function used with `for_each` takes a single argument `pair`, and then
  1396. uses `first` and `second` to access the subparts of the pair. Also, notice
  1397. how the `to<char const*>` function is used on the name of the member? This
  1398. converts the compile-time string to a `constexpr char const*` so it can
  1399. `cout`ed. Since it can be annoying to always use `first` and `second` to
  1400. fetch the subparts of the pair, we can also use the `fuse` function to wrap
  1401. our lambda and make it a binary lambda instead:
  1402. @snippet example/tutorial/introspection.adapt.cpp for_each.fuse
  1403. Now, it looks much cleaner. As we just mentioned, `Struct`s are seen as a kind
  1404. of sequence of pairs for the purpose of iteration. In fact, a `Struct` can
  1405. even be searched like an associative data structure whose keys are the names
  1406. of the members, and whose values are the members themselves:
  1407. @snippet example/tutorial/introspection.adapt.cpp at_key
  1408. @note
  1409. The `_s` user-defined literal creates a compile-time `hana::string`. It is
  1410. located in the `boost::hana::literals` namespace. Note that it is not part
  1411. of the standard yet, but it is supported by Clang and GCC. If you want to
  1412. stay 100% standard, you can use the `BOOST_HANA_STRING` macro instead.
  1413. The main difference between a `Struct` and a `hana::map` is that a map can be
  1414. modified (keys can be added and removed), while a `Struct` is immutable.
  1415. However, you can easily convert a `Struct` into a `hana::map` with `to<map_tag>`,
  1416. and then you can manipulate it in a more flexible way.
  1417. @snippet example/tutorial/introspection.adapt.cpp to<map_tag>
  1418. Using the `BOOST_HANA_DEFINE_STRUCT` macro to adapt a `struct` is convenient,
  1419. but sometimes one can't modify the type that needs to be adapted. In these
  1420. cases, the `BOOST_HANA_ADAPT_STRUCT` macro can be used to adapt a `struct` in
  1421. a ad-hoc manner:
  1422. @snippet example/tutorial/introspection.adapt.cpp BOOST_HANA_ADAPT_STRUCT
  1423. @note
  1424. The `BOOST_HANA_ADAPT_STRUCT` macro must be used at global scope.
  1425. The effect is exactly the same as with the `BOOST_HANA_DEFINE_STRUCT` macro,
  1426. except you do not need to modify the type you want to adapt, which is
  1427. sometimes useful. Finally, it is also possible to define custom accessors
  1428. by using the `BOOST_HANA_ADAPT_ADT` macro:
  1429. @snippet example/tutorial/introspection.adapt.cpp BOOST_HANA_ADAPT_ADT
  1430. This way, the names used to access the members of the `Struct` will be those
  1431. specified, and the associated function will be called on the `Struct` when
  1432. retrieving that member. Before we move on to a concrete example of using these
  1433. introspection features, it should also be mentioned that `struct`s can be
  1434. adapted without using macros. This advanced interface for defining `Struct`s
  1435. can be used for example to specify keys that are not compile-time strings.
  1436. The advanced interface is described in the documentation of the `Struct`
  1437. concept.
  1438. @subsection tutorial-introspection-json Example: generating JSON
  1439. Let's now move on with a concrete example of using the introspection
  1440. capabilities we just presented for printing custom objects as JSON.
  1441. Our end goal is to have something like this:
  1442. @snippet example/tutorial/introspection.json.cpp usage
  1443. And the output, after passing it through a JSON pretty-printer,
  1444. should look like
  1445. @code{.json}
  1446. [
  1447. {
  1448. "name": "John",
  1449. "last_name": "Doe",
  1450. "age": 30
  1451. },
  1452. {
  1453. "brand": "Audi",
  1454. "model": "A4"
  1455. },
  1456. {
  1457. "brand": "BMW",
  1458. "model": "Z3"
  1459. }
  1460. ]
  1461. @endcode
  1462. First, let's define a couple of utility functions to make string manipulation
  1463. easier:
  1464. @snippet example/tutorial/introspection.json.cpp utilities
  1465. The `quote` and the `to_json` overloads are pretty self-explanatory. The
  1466. `join` function, however, might need a bit of explanation. Basically, the
  1467. `intersperse` function takes a sequence and a separator, and returns a new
  1468. sequence with the separator in between each pair of elements of the original
  1469. sequence. In other words, we take a sequence of the form `[x1, ..., xn]` and
  1470. turn it into a sequence of the form `[x1, sep, x2, sep, ..., sep, xn]`.
  1471. Finally, we fold the resulting sequence with the `_ + _` function object,
  1472. which is equivalent to `std::plus<>{}`. Since our sequence contains
  1473. `std::string`s (we assume it does), this has the effect of concatenating
  1474. all the strings of the sequence into one big string. Now, let's define
  1475. how to print a `Sequence`:
  1476. @snippet example/tutorial/introspection.json.cpp Sequence
  1477. First, we use the `transform` algorithm to turn our sequence of objects into
  1478. a sequence of `std::string`s in JSON format. Then, we join that sequence with
  1479. commas and we enclose it with `[]` to denote a sequence in JSON notation.
  1480. Simple enough? Let's now take a look at how to print user-defined types:
  1481. @snippet example/tutorial/introspection.json.cpp Struct
  1482. Here, we use the `keys` method to retrieve a `tuple` containing the names of
  1483. the members of the user-defined type. Then, we `transform` that sequence into
  1484. a sequence of `"name" : member` strings, which we then `join` and enclose with
  1485. `{}`, which is used to denote objects in JSON notation. And that's it!
  1486. @section tutorial-containers Generalities on containers
  1487. ------------------------------------------------------------------------------
  1488. This section explains several important notions about Hana's containers: how
  1489. to create them, the lifetime of their elements and other concerns.
  1490. @subsection tutorial-containers-creating Container creation
  1491. While the usual way of creating an object in C++ is to use its constructor,
  1492. heterogeneous programming makes things a bit more complicated. Indeed, in
  1493. most cases, one is not interested in (or even aware of) the actual type of
  1494. the heterogeneous container to be created. At other times, one could write
  1495. out that type explicitly, but it would be redundant or cumbersome to do so.
  1496. For this reason, Hana uses a different approach borrowed from `std::make_tuple`
  1497. to create new containers. Much like one can create a `std::tuple` with
  1498. `std::make_tuple`, a `hana::tuple` can be created with `hana::make_tuple`.
  1499. However, more generally, containers in Hana may be created with the `make`
  1500. function:
  1501. @snippet example/tutorial/containers.cpp make<tuple_tag>
  1502. In fact, `make_tuple` is just a shortcut for `make<tuple_tag>` so you don't
  1503. have to type `boost::hana::make<boost::hana::tuple_tag>` when you are out of
  1504. Hana's namespace. Simply put, `make<...>` is is used all around the library
  1505. to create different types of objects, thus generalizing the `std::make_xxx`
  1506. family of functions. For example, one can create a `hana::range` of
  1507. compile-time integers with `make<range_tag>`:
  1508. @snippet example/tutorial/containers.cpp make<range_tag>
  1509. > These types with a trailing `_tag` are dummy types __representing__ a family
  1510. > of heterogeneous containers (`hana::tuple`, `hana::map`, etc..). Tags are
  1511. > documented in the section on [Hana's core](@ref tutorial-core-tags).
  1512. For convenience, whenever a component of Hana provides a `make<xxx_tag>`
  1513. function, it also provides the `make_xxx` shortcut to reduce typing. Also, an
  1514. interesting point that can be raised in this example is the fact that `r` is
  1515. `constexpr`. In general, whenever a container is initialized with constant
  1516. expressions only (which is the case for `r`), that container may be marked
  1517. as `constexpr`.
  1518. So far, we have only created containers with the `make_xxx` family of
  1519. functions. However, some containers do provide constructors as part of
  1520. their interface. For example, one can create a `hana::tuple` just like
  1521. one would create a `std::tuple`:
  1522. @snippet example/tutorial/containers.cpp tuple_constructor
  1523. When constructors (or any member function really) are part of the public
  1524. interface, they will be documented on a per-container basis. However,
  1525. in the general case, one should not take for granted that a container
  1526. can be constructed as the tuple was constructed above. For example,
  1527. trying to create a `hana::range` that way will __not__ work:
  1528. @code{.cpp}
  1529. hana::range<???> xs{hana::int_c<3>, hana::int_c<10>};
  1530. @endcode
  1531. In fact, we can't even specify the type of the object we'd like to create in
  1532. that case, because the exact type of a `hana::range` is implementation-defined,
  1533. which brings us to the next section.
  1534. @subsection tutorial-containers-types Container types
  1535. The goal of this section is to clarify what can be expected from the types of
  1536. Hana's containers. Indeed, so far, we always let the compiler deduce the
  1537. actual type of containers by using the `make_xxx` family of functions along
  1538. with `auto`. But in general, what can we say about the type of a container?
  1539. @snippet example/tutorial/containers.cpp types
  1540. The answer is that it depends. Some containers have well defined types, while
  1541. others do not specify their representation. In this example, the type of the
  1542. object returned by `make_tuple` is well-defined, while the type returned by
  1543. `make_range` is implementation-defined:
  1544. @snippet example/tutorial/containers.cpp types_maximally_specified
  1545. This is documented on a per-container basis; when a container has an
  1546. implementation-defined representation, a note explaining exactly what
  1547. can be expected from that representation is included in the container's
  1548. description. There are several reasons for leaving the representation of
  1549. a container unspecified; they are explained in the
  1550. [rationales](@ref tutorial-rationales-container_representation).
  1551. When the representation of a container is implementation-defined, one must
  1552. be careful not to make any assumptions about it, unless those assumption
  1553. are explicitly allowed in the documentation of the container. For example,
  1554. assuming that one can safely inherit from a container or that the elements
  1555. in the container are stored in the same order as specified in its template
  1556. argument list is generally not safe.
  1557. @subsubsection tutorial-containers-types-overloading Overloading on container types
  1558. While necessary, leaving the type of some containers unspecified makes some
  1559. things very difficult to achieve, like overloading functions on heterogeneous
  1560. containers:
  1561. @code{cpp}
  1562. template <typename T>
  1563. void f(std::vector<T> xs) {
  1564. // ...
  1565. }
  1566. template <typename ...???>
  1567. void f(unspecified-range-type<???> r) {
  1568. // ...
  1569. }
  1570. @endcode
  1571. The `is_a` utility is provided for this reason (and others). `is_a` allows
  1572. checking whether a type is a precise kind of container using its tag,
  1573. regardless of the actual type of the container. For example, the above
  1574. example could be rewritten as
  1575. @snippet example/tutorial/containers.cpp overloading
  1576. This way, the second overload of `f` will only match when `R` is a type whose
  1577. tag is `range_tag`, regardless of the exact representation of that range. Of
  1578. course, `is_a` can be used with any kind of container: `tuple`, `map`, `set`
  1579. and so on.
  1580. @subsection tutorial-containers-elements Container elements
  1581. In Hana, containers own their elements. When a container is created, it makes
  1582. a _copy_ of the elements used to initialize it and stores them inside the
  1583. container. Of course, unnecessary copies are avoided by using move semantics.
  1584. Because of those owning semantics, the lifetime of the objects inside the
  1585. container is the same as that of the container.
  1586. @snippet example/tutorial/containers.cpp lifetime
  1587. Much like containers in the standard library, containers in Hana expect their
  1588. elements to be objects. For this reason, references _may not_ be stored in
  1589. them. When references must be stored inside a container, one should use a
  1590. `std::reference_wrapper` instead:
  1591. @snippet example/tutorial/containers.cpp reference_wrapper
  1592. @section tutorial-algorithms Generalities on algorithms
  1593. ------------------------------------------------------------------------------
  1594. Much like the previous section introduced general but important notions about
  1595. heterogeneous containers, this section introduces general notions about
  1596. heterogeneous algorithms.
  1597. @subsection tutorial-algorithms-value By-value semantics
  1598. Algorithms in Hana always return a new container holding the result. This
  1599. allows one to easily chain algorithms by simply using the result of the first
  1600. as the input of the second. For example, to apply a function to every element
  1601. of a tuple and then reverse the result, one simply has to connect the `reverse`
  1602. and `transform` algorithms:
  1603. @snippet example/tutorial/algorithms.cpp reverse_transform
  1604. This is different from the algorithms of the standard library, where one has
  1605. to provide iterators to the underlying sequence. For reasons documented in the
  1606. [rationales](@ref tutorial-rationales-iterators), an iterator-based design was
  1607. considered but was quickly dismissed in favor of composable and efficient
  1608. abstractions better suited to the very particular context of heterogeneous
  1609. programming.
  1610. One might also think that returning full sequences that own their elements
  1611. from an algorithm would lead to tons of undesirable copies. For example, when
  1612. using `reverse` and `transform`, one could think that an intermediate copy is
  1613. made after the call to `transform`:
  1614. @snippet example/tutorial/algorithms.cpp reverse_transform_copy
  1615. To make sure this does not happen, Hana uses perfect forwarding and move
  1616. semantics heavily so it can provide an almost optimal runtime performance.
  1617. So instead of doing a copy, a move occurs between `reverse` and `transform`:
  1618. @snippet example/tutorial/algorithms.cpp reverse_transform_move
  1619. Ultimately, the goal is that code written using Hana should be equivalent to
  1620. clever hand-written code, except it should be enjoyable to write. Performance
  1621. considerations are explained in depth in their own [section]
  1622. (@ref tutorial-performance).
  1623. @subsection tutorial-algorithms-laziness (Non-)Laziness
  1624. Algorithms in Hana are not lazy. When an algorithm is called, it does its
  1625. job and returns a new sequence containing the result, end of the story.
  1626. For example, calling the `permutations` algorithm on a large sequence is
  1627. a stupid idea, because Hana will actually compute all the permutations:
  1628. @code{cpp}
  1629. auto perms = hana::permutations(hana::make_tuple(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
  1630. // perms has 3 628 800 elements, and your compiler just crashed
  1631. @endcode
  1632. To contrast, algorithms in Boost.Fusion return views which hold the original
  1633. sequence by reference and apply the algorithm on demand, as the elements of
  1634. the sequence are accessed. This leads to subtle lifetime issues, like having
  1635. a view that refers to a sequence that was destroyed. Hana's design assumes
  1636. that most of the time, we want to access all or almost all the elements in a
  1637. sequence anyway, and hence performance is not a big argument in favor of
  1638. laziness.
  1639. @subsection tutorial-algorithms-codegen What is generated?
  1640. Algorithms in Hana are a bit special with respect to the runtime code they are
  1641. expanded into. The goal of this subsection is not to explain exactly what code
  1642. is generated, which depends on the compiler anyway, but to give a feel for
  1643. things. Basically, a Hana algorithm is like an unrolled version of an
  1644. equivalent classical algorithm. Indeed, since the bounds of the processed
  1645. sequence are known at compile-time, it makes sense that we can unroll the
  1646. loop over the sequence. For example, let's consider the `for_each` algorithm:
  1647. @code{cpp}
  1648. auto xs = hana::make_tuple(0, 1, 2, 3);
  1649. hana::for_each(xs, f);
  1650. @endcode
  1651. If `xs` was a runtime sequence instead of a tuple, its length would only be
  1652. known at runtime and the above code would have to be implemented as a loop:
  1653. @code{cpp}
  1654. for (int i = 0; i < xs.size(); ++i) {
  1655. f(xs[i]);
  1656. }
  1657. @endcode
  1658. However, in our case, the length of the sequence is known at compile-time and
  1659. so we don't have to check the index at each iteration. Hence, we can just
  1660. write:
  1661. @code{cpp}
  1662. f(xs[0_c]);
  1663. f(xs[1_c]);
  1664. f(xs[2_c]);
  1665. f(xs[3_c]);
  1666. @endcode
  1667. The main difference here is that no bound checking and index increment is done
  1668. at each step, because there is no index anymore; the loop was effectively
  1669. unrolled. In some cases, this can be desirable for performance reasons. In
  1670. other cases, this can be detrimental to performance because it causes the
  1671. code size to grow. As always, performance is a tricky subject and whether
  1672. you actually want loop unrolling to happen should be tackled on a case-by-case
  1673. basis. As a rule of thumb, algorithms processing all (or a subset) of the
  1674. elements of a container are unrolled. In fact, if you think about it, this
  1675. unrolling is the only way to go for heterogeneous sequences, because different
  1676. elements of the sequence may have different types. As you might have noticed,
  1677. we're not using normal indices into the tuple, but compile-time indices, which
  1678. can't be generated by a normal `for` loop. In other words, the following does
  1679. not make sense:
  1680. @code{cpp}
  1681. for (??? i = 0_c; i < xs.size(); ++i) {
  1682. f(xs[i]);
  1683. }
  1684. @endcode
  1685. @subsection tutorial-algorithms-effects Side effects and purity
  1686. By default, Hana assumes functions to be pure. A pure function is a function
  1687. that has no side-effects at all. In other words, it is a function whose effect
  1688. on the program is solely determined by its return value. In particular, such a
  1689. function may not access any state that outlives a single invocation of the
  1690. function. These functions have very nice properties, like the ability to
  1691. reason mathematically about them, to reorder or even eliminate calls, and
  1692. so on. Except where specified otherwise, all functions used with Hana (i.e.
  1693. used in higher order algorithms) should be pure. In particular, functions
  1694. passed to higher order algorithms are not guaranteed to be called any
  1695. specific number of times. Furthermore, the order of execution is generally
  1696. not specified and should therefore not be taken for granted. If this lack of
  1697. guarantees about function invocations seems crazy, consider the following use
  1698. of the `any_of` algorithm:
  1699. @snippet example/tutorial/algorithms.cpp effects
  1700. @note
  1701. For this to work, the external adapters for `std::integral_constant` contained
  1702. in `<boost/hana/ext/std/integral_constant.hpp>` must be included.
  1703. According to the previous section on unrolling, this algorithm should be
  1704. expanded into something like:
  1705. @code{cpp}
  1706. auto xs = hana::make_tuple("hello"s, 1.2, 3);
  1707. auto pred = [](auto x) { return std::is_integral<decltype(x)>{}; };
  1708. auto r = hana::bool_c<
  1709. pred(xs[0_c]) ? true :
  1710. pred(xs[1_c]) ? true :
  1711. pred(xs[2_c]) ? true :
  1712. false
  1713. >;
  1714. BOOST_HANA_CONSTANT_CHECK(r);
  1715. @endcode
  1716. Of course, the above code can't work as-is, because we're calling `pred` inside
  1717. something that would have to be a constant expression, but `pred` is a lambda
  1718. (and lambdas can't be called in constant expressions). However, whether any of
  1719. these objects has an integral type is clearly known at compile-time, and hence
  1720. we would expect that computing the answer only involves compile-time
  1721. computations. In fact, this is exactly what Hana does, and the above
  1722. algorithm is expanded into something like:
  1723. @snippet example/tutorial/algorithms.cpp effects.codegen
  1724. @note
  1725. As you will be able to deduce from the next section on cross-phase computations,
  1726. the implementation of `any_of` must actually be more general than this. However,
  1727. this [lie-to-children][] is perfect for educational purposes.
  1728. As you can see, the predicate is never even executed; only its result type on
  1729. a particular object is used. Regarding the order of evaluation, consider the
  1730. `transform` algorithm, which is specified (for tuples) as:
  1731. @code{cpp}
  1732. hana::transform(hana::make_tuple(x1, ..., xn), f) == hana::make_tuple(f(x1), ..., f(xn))
  1733. @endcode
  1734. Since `make_tuple` is a function, and since the evaluation order for the
  1735. arguments of a function is unspecified, the order in which `f` is called
  1736. on each element of the tuple is unspecified too. If one sticks to pure
  1737. functions, everything works fine and the resulting code is often easier
  1738. to understand. However, some exceptional algorithms like `for_each` do
  1739. expect impure functions, and they guarantee an order of evaluation. Indeed,
  1740. a `for_each` algorithm that would only take pure functions would be pretty
  1741. much useless. When an algorithm can accept an impure function or guarantees
  1742. some order of evaluation, the documentation for that algorithm will mention
  1743. it explicitly. However, by default, no guarantees may be taken for granted.
  1744. @subsection tutorial-algorithms-cross_phase Cross-phase algorithms
  1745. This section introduces the notion of cross-phase computations and algorithms.
  1746. In fact, we have already used cross-phase algorithms in the [quick start]
  1747. (@ref tutorial-quickstart), for example with `filter`, but we did not explain
  1748. exactly what was happening at that time. But before we introduce cross-phase
  1749. algorithms, let's define what we mean by _cross-phase_. The phases we're
  1750. referring to here are the compilation and the execution of a program. In C++
  1751. as in most statically typed languages, there is a clear distinction between
  1752. compile-time and runtime; this is called phase distinction. When we speak of
  1753. a cross-phase computation, we mean a computation that is somehow performed
  1754. across those phases; i.e. that is partly executed at compile-time and partly
  1755. executed at runtime.
  1756. Like we saw in earlier examples, some functions are able to return something
  1757. that can be used at compile-time even when they are called on a runtime value.
  1758. For example, let's consider the `length` function applied to a non-`constexpr`
  1759. container:
  1760. @snippet example/tutorial/algorithms.cpp cross_phase.setup
  1761. Obviously, the tuple can't be made `constexpr`, since it contains runtime
  1762. `std::string`s. Still, even though it is not called on a constant expression,
  1763. `length` returns something that can be used at compile-time. If you think of
  1764. it, the size of the tuple is known at compile-time regardless of its content,
  1765. and hence it would only make sense for this information to be available to us
  1766. at compile-time. If that seems surprising, think about `std::tuple` and
  1767. `std::tuple_size`:
  1768. @snippet example/tutorial/algorithms.cpp cross_phase.std::tuple_size
  1769. Since the size of the tuple is encoded in its type, it is always available
  1770. at compile-time regardless of whether the tuple is `constexpr` or not. In Hana,
  1771. this is implemented by having `length` return an `IntegralConstant`. Since an
  1772. `IntegralConstant`'s value is encoded in its type, the result of `length` is
  1773. contained in the type of the object it returns, and the length is therefore
  1774. known at compile-time. Because `length` goes from a runtime value (the
  1775. container) to a compile-time value (the `IntegralConstant`), `length` is a
  1776. trivial example of a cross-phase algorithm (trivial because it does not really
  1777. manipulate the tuple). Another algorithm that is very similar to `length` is
  1778. the `is_empty` algorithm, which returns whether a container is empty:
  1779. @snippet example/tutorial/algorithms.cpp cross_phase.is_empty
  1780. More generally, any algorithm that takes a container whose value is known at
  1781. runtime but queries something that can be known at compile-time should be able
  1782. to return an `IntegralConstant` or another similar compile-time value. Let's
  1783. make things slightly more complicated by considering the `any_of` algorithm,
  1784. which we already encountered in the previous section:
  1785. @snippet example/tutorial/algorithms.cpp cross_phase.any_of_runtime
  1786. In this example, the result can't be known at compile-time, because the
  1787. predicate returns a `bool` that is the result of comparing two `std::string`s.
  1788. Since `std::string`s can't be compared at compile-time, the predicate must
  1789. operate at runtime, and the overall result of the algorithm can then only be
  1790. known at runtime too. However, let's say we used `any_of` with the following
  1791. predicate instead:
  1792. @snippet example/tutorial/algorithms.cpp cross_phase.any_of_compile_time
  1793. @note
  1794. For this to work, the external adapters for `std::integral_constant` contained
  1795. in `<boost/hana/ext/std/integral_constant.hpp>` must be included.
  1796. First, since the predicate is only querying information about the type of each
  1797. element of the tuple, it is clear that its result can be known at compile-time.
  1798. Since the number of elements in the tuple is also known at compile-time, the
  1799. overall result of the algorithm can, in theory, be known at compile-time. More
  1800. precisely, what happens is that the predicate returns a value initialized
  1801. `std::is_same<...>`, which inherits from `std::integral_constant`. Hana
  1802. recognizes these objects, and the algorithm is written in such a way that it
  1803. preserves the `compile-time`ness of the predicate's result. In the end,
  1804. `any_of` hence returns an `IntegralConstant` holding the result of the
  1805. algorithm, and we use the compiler's type deduction in a clever way to make
  1806. it look easy. Hence, it would be equivalent to write (but then you would need
  1807. to already know the result of the algorithm!):
  1808. @snippet example/tutorial/algorithms.cpp cross_phase.any_of_explicit
  1809. Ok, so some algorithms are able to return compile-time values when their input
  1810. satisfies some constraints with respect to `compile-time`ness. However, other
  1811. algorithms are more restrictive and they _require_ their inputs to satisfy some
  1812. constraints regarding `compile-time`ness, without which they are not able to
  1813. operate at all. An example of this is `filter`, which takes a sequence and a
  1814. predicate, and returns a new sequence containing only those elements for which
  1815. the predicate is satisfied. `filter` requires the predicate to return an
  1816. `IntegralConstant`. While this requirement may seem stringent, it really makes
  1817. sense if you think about it. Indeed, since we're removing some elements from
  1818. the heterogeneous sequence, the type of the resulting sequence depends on the
  1819. result of the predicate. Hence, the result of the predicate has to be known at
  1820. compile-time for the compiler to be able to assign a type to the returned
  1821. sequence. For example, consider what happens when we try to filter a
  1822. heterogeneous sequence as follows:
  1823. @code{cpp}
  1824. auto animals = hana::make_tuple(Fish{"Nemo"}, Cat{"Garfield"}, Dog{"Snoopy"});
  1825. auto no_garfield = hana::filter(animals, [](auto animal) {
  1826. return animal.name != "Garfield"s;
  1827. });
  1828. @endcode
  1829. Clearly, we know that the predicate will only return false on the second
  1830. element, and hence the result _should be_ a `[Fish, Dog]` tuple. However,
  1831. the compiler has no way of knowing this since the predicate's result is the
  1832. result of a runtime computation, which happens way after the compiler has
  1833. finished its job. Hence, the compiler does not have enough information to
  1834. determine the return type of the algorithm. However, we could `filter` the
  1835. same sequence with any predicate whose result is available at compile-time:
  1836. @snippet example/tutorial/algorithms.cpp cross_phase.filter
  1837. Since the predicate returns an `IntegralConstant`, we know which elements
  1838. of the heterogeneous sequence we'll be keeping at compile-time. Hence, the
  1839. compiler is able to figure out the return type of the algorithm. Other
  1840. algorithms like `partition` and `sort` work similarly; special algorithm
  1841. requirements are always documented, just read the reference documentation
  1842. of an algorithm before using it to avoid surprises.
  1843. This is the end of the section on algorithms. While this constitutes a fairly
  1844. complete explanation of phase interaction inside algorithms, a deeper
  1845. understanding can be gained by reading the [advanced section]
  1846. (@ref tutorial-appendix-constexpr) on `constexpr` and the reference
  1847. for `Constant` and `IntegralConstant`.
  1848. @warning
  1849. Hana's algorithms are `constexpr` function objects instead of being template
  1850. functions. This allows passing them to higher-order algorithms, which is very
  1851. useful. However, since those function objects are defined at namespace scope
  1852. in the header files, this causes each translation unit to see a different
  1853. algorithm object. Hence, the address of an algorithm function object is not
  1854. guaranteed to be unique across translation units, which can cause an ODR
  1855. violation if one relies on such an address. So, in short, do not rely on the
  1856. uniqueness of the address of any global object provided by Hana, which does
  1857. not make sense in the general case anyway because such objects are `constexpr`.
  1858. See [issue #76](https://github.com/boostorg/hana/issues/76) for more information.
  1859. @section tutorial-performance Performance considerations
  1860. ------------------------------------------------------------------------------
  1861. C++ programmers love performance, so here's a whole section dedicated to it.
  1862. Since Hana lives on the frontier between runtime and compile-time computations,
  1863. we are not only interested in runtime performance, but also compile-time
  1864. performance. Since both topics are pretty much disjoint, we treat them
  1865. separately below.
  1866. @note
  1867. The benchmarks presented in this section are updated automatically when we
  1868. push to the repository. If you notice results that do not withstand the
  1869. claims made here, open a [GitHub issue][Hana.issues]; it could be a
  1870. performance regression.
  1871. @warning
  1872. As of writing this, not all of Hana's containers are optimized. Implementing
  1873. Hana was a big enough challenge that containers were initially written naively
  1874. and are now in the process of being rigorously optimized. In particular, the
  1875. associative containers (`hana::map` and `hana::set`) have a pretty bad
  1876. compile-time behavior because of their naive implementation, and their runtime
  1877. behavior also seems to be problematic in some cases. Improving this situation
  1878. is in the TODO list.
  1879. @subsection tutorial-performance-compile Compile-time performance
  1880. C++ metaprogramming brings its share of awful things. One of the most annoying
  1881. and well-known problem associated to it is interminable compilation times.
  1882. Hana claims to be more compile-time efficient than its predecessors; this is
  1883. a bold claim and we will now try to back it. Of course, Hana can't do miracles;
  1884. metaprogramming is a byproduct of the C++ template system and the compiler is
  1885. not meant to be used as an interpreter for some meta language. However, by
  1886. using cutting edge and intensely benchmarked techniques, Hana is able to
  1887. minimize the strain on the compiler.
  1888. @note
  1889. While Hana has better compile-times than pre-C++11 metaprogramming libraries,
  1890. modern libraries supporting only type-level computations (such as [Brigand][])
  1891. can provide better compile-times, at the cost of generality. Indeed, Hana's
  1892. ability to manipulate runtime values comes at a compile-time cost, no matter
  1893. how hard we try to mitigate it. If you want to use Hana for intensive type-level
  1894. computations, you should benchmark and see whether it suits you.
  1895. Before we dive, let me make a quick note on the methodology used to measure
  1896. compile-time performance in Hana. Previous metaprogramming libraries measured
  1897. the compile-time complexity of their meta-algorithms and meta-sequences by
  1898. looking at the number of instantiations the compiler had to perform. While
  1899. easy to understand, this way of measuring the compile-time complexity actually
  1900. does not give us a lot of information regarding the compilation time, which
  1901. is what we're interested in minimizing at the end of the day. Basically, the
  1902. reason for this is that template metaprogramming is such a twisted model of
  1903. computation that it's very hard to find a standard way of measuring the
  1904. performance of algorithms. Hence, instead of presenting meaningless complexity
  1905. analyses, we prefer to benchmark everything on every supported compiler and to
  1906. pick the best implementation on that compiler. Also note that the benchmarks
  1907. we present here are quite precise. Indeed, even though we do not take multiple
  1908. measurements and take their mean or something similar to reduce incertitude,
  1909. the benchmarks are very stable when they are regenerated, which suggests a
  1910. reasonably good precision. Now, let's dive.
  1911. First, Hana minimizes its dependency on the preprocessor. In addition to
  1912. yielding cleaner error messages in many cases, this reduces the overall
  1913. parsing and preprocessing time for header files. Also, because Hana only
  1914. supports cutting edge compilers, there are very few workarounds in the
  1915. library, which results in a cleaner and smaller library. Finally, Hana
  1916. minimizes reliance on any kind of external dependencies. In particular,
  1917. it only uses other Boost libraries in a few specific cases, and it does
  1918. not rely on the standard library for the largest part. There are several
  1919. reasons (other than include times) for doing so; they are documented in
  1920. the [rationales](@ref tutorial-rationales-dependencies).
  1921. Below is a chart showing the time required to include different libraries. The
  1922. chart shows the time for including everything in the (non-external) public API
  1923. of each library. For example, for Hana this means the `<boost/hana.hpp>` header,
  1924. which excludes the external adapters. For other libraries like Boost.Fusion,
  1925. this means including all the public headers in the `boost/fusion/` directory,
  1926. but not the adapters for external libraries like the MPL.
  1927. <div class="benchmark-chart"
  1928. style="min-width: 310px; height: 400px; margin: 0 auto"
  1929. data-dataset="benchmark.including.compile.json">
  1930. </div>
  1931. In addition to reduced preprocessing times, Hana uses modern techniques to
  1932. implement heterogeneous sequences and algorithms in the most compile-time
  1933. efficient way possible. Before jumping to the compile-time performance of
  1934. the algorithms, we will have a look at the compile-time cost of creating
  1935. heterogeneous sequences. Indeed, since we will be presenting algorithms that
  1936. work on sequences, we must be aware of the cost of creating the sequences
  1937. themselves, since that will influence the benchmarks for the algorithms.
  1938. The following chart presents the compile-time cost of creating a sequence
  1939. of `n` heterogeneous elements.
  1940. <div class="benchmark-chart"
  1941. style="min-width: 310px; height: 400px; margin: 0 auto"
  1942. data-dataset="benchmark.make.compile.json">
  1943. </div>
  1944. @note
  1945. You can zoom on the chart by selecting an area to zoom into. Also, you can
  1946. hide a series of points by clicking on it in the legend on the right.
  1947. The benchmark methodology is to always create the sequences in the most
  1948. efficient way possible. For Hana and `std::tuple`, this simply means using
  1949. the appropriate `make_tuple` function. However, for the MPL, this means
  1950. creating a `mpl::vectorN` of size up to 20, and then using `mpl::push_back`
  1951. to create larger vectors. We use a similar technique for Fusion sequences.
  1952. The reason for doing so is that Fusion and MPL sequences have fixed size
  1953. limits, and the techniques used here have been found to be the fastest way
  1954. to create longer sequences.
  1955. For completeness, we also present the compile-time cost of creating a
  1956. `std::array` with `n` elements. However, note that `std::array` can only
  1957. hold elements with a single type, so we're comparing apples and oranges
  1958. here. As you can see, the cost of creating a `std::array` is constant and
  1959. essentially inexistent (the non-zero overhead is that of simply including
  1960. the `<array>` header). Hence, while Hana provides improved compile-times
  1961. over other heterogeneous containers, please stick with normal homogeneous
  1962. containers if that's all you need for your application; your compile-times
  1963. will be much faster that way.
  1964. You can also see that creating sequences has a non-negligible cost. Actually,
  1965. this is really the most expensive part of doing heterogeneous computations,
  1966. as you will see in the following charts. Hence, when you look at the charts
  1967. below, keep in mind the cost of merely creating the sequences. Also note that
  1968. only the most important algorithms will be presented here, but the [Metabench][]
  1969. project provides micro benchmarks for compile-time performance for almost all
  1970. of Hana's algorithms. Also, the benchmarks we present compare several different
  1971. libraries. However, since Hana and Fusion can work with values and not only
  1972. types, comparing their algorithms with type-only libraries like MPL is not
  1973. really fair. Indeed, Hana and Fusion algorithms are more powerful since they
  1974. also allow runtime effects to be performed. However, the comparison between
  1975. Fusion and Hana is fair, because both libraries are just as powerful (strictly
  1976. speaking). Finally, we can't show benchmarks of the algorithms for `std::tuple`,
  1977. because the standard does not provide equivalent algorithms. Of course, we
  1978. could use Hana's external adapters, but that would not be a faithful comparison.
  1979. The first algorithm which is ubiquitous in metaprogramming is `transform`.
  1980. It takes a sequence and a function, and returns a new sequence containing the
  1981. result of applying the function to each element. The following chart presents
  1982. the compile-time performance of applying `transform` to a sequence of `n`
  1983. elements. The `x` axis represents the number of elements in the sequence, and
  1984. the `y` axis represents the compilation time in seconds. Also note that we're
  1985. using the `transform` equivalent in each library; we're not using Hana's
  1986. `transform` through the Boost.Fusion adapters, for example, because we really
  1987. want to benchmark their implementation against ours.
  1988. <div class="benchmark-chart"
  1989. style="min-width: 310px; height: 400px; margin: 0 auto"
  1990. data-dataset="benchmark.transform.compile.json">
  1991. </div>
  1992. Here, we can see that Hana's tuple performs better than all the other
  1993. alternatives. This is mainly due to the fact that we use C++11 variadic
  1994. parameter pack expansion to implement this algorithm under the hood, which
  1995. is quite efficient.
  1996. Before we move on, it is important to mention something regarding the benchmark
  1997. methodology for Fusion algorithms. Some algorithms in Fusion are lazy, which
  1998. means that they don't actually perform anything, but simply return a modified
  1999. view to the original data. This is the case of `fusion::transform`, which
  2000. simply returns a transformed view that applies the function to each element
  2001. of the original sequence as those elements are accessed. If we want to
  2002. benchmark anything at all, we need to force the evaluation of that view, as
  2003. would eventually happen when accessing the elements of the sequence in real
  2004. code. However, for complex computations with multiple layers, a lazy approach
  2005. may yield a substantially different compile-time profile. Of course, this
  2006. difference is poorly represented in micro benchmarks, so keep in mind that
  2007. these benchmarks only give a part of the big picture. For completeness in the
  2008. rest of the section, we will mention when a Fusion algorithm is lazy, so that
  2009. you know when we're _artificially_ forcing the evaluation of the algorithm for
  2010. the purpose of benchmarking.
  2011. @note
  2012. We are currently considering adding lazy views to Hana. If this feature is
  2013. important to you, please let us know by commenting
  2014. [this issue](https://github.com/boostorg/hana/issues/193).
  2015. The second important class of algorithms are folds. Folds can be used to
  2016. implement many other algorithms like `count_if`, `minimum` and so on.
  2017. Hence, a good compile-time performance for fold algorithms ensures a good
  2018. compile-time performance for those derived algorithms, which is why we're
  2019. only presenting folds here. Also note that all the non-monadic fold variants
  2020. are somewhat equivalent in terms of compile-time, so we only present the left
  2021. folds. The following chart presents the compile-time performance of applying
  2022. `fold_left` to a sequence of `n` elements. The `x` axis represents the number
  2023. of elements in the sequence, and the `y` axis represents the compilation time
  2024. in seconds. The function used for folding is a dummy function that does nothing.
  2025. In real code, you would likely fold with a nontrivial operation, so the curves
  2026. would be worse than that. However, these are micro benchmarks and hence they
  2027. only show the performance of the algorithm itself.
  2028. <div class="benchmark-chart"
  2029. style="min-width: 310px; height: 400px; margin: 0 auto"
  2030. data-dataset="benchmark.fold_left.compile.json">
  2031. </div>
  2032. The third and last algorithm that we present here is the `find_if` algorithm.
  2033. This algorithm is difficult to implement efficiently, because it requires
  2034. stopping at the first element which satisfies the given predicate. For the
  2035. same reason, modern techniques don't really help us here, so this algorithm
  2036. constitutes a good test of the implementation quality of Hana, without taking
  2037. into account the free lunch given to use by C++14.
  2038. <div class="benchmark-chart"
  2039. style="min-width: 310px; height: 400px; margin: 0 auto"
  2040. data-dataset="benchmark.find_if.compile.json">
  2041. </div>
  2042. As you can see, Hana performs better than Fusion, and as well as MPL, yet
  2043. Hana's `find_if` can be used with values too, unlike MPL's. This concludes
  2044. the section on compile-time performance. In case you want to see the
  2045. performance of an algorithm that we have not presented here, the [Metabench][]
  2046. project provides compile-time benchmarks for most of Hana's algorithms.
  2047. @subsection tutorial-performance-runtime Runtime performance
  2048. Hana was designed to be very efficient at runtime. But before we dive into the
  2049. details, let's clarify one thing. Hana being a metaprogramming library which
  2050. allows manipulating both types and values, it does not always make sense to
  2051. even talk about runtime performance. Indeed, for type-level computations and
  2052. computations on `IntegralConstant`s, runtime performance is simply not a
  2053. concern, because the result of the computation is contained in a _type_, which
  2054. is a purely compile-time entity. In other words, these computations involve
  2055. only compile-time work, and no code is even generated to perform these
  2056. computations at runtime. The only case where it makes sense to discuss runtime
  2057. performance is when manipulating runtime values in heterogeneous containers
  2058. and algorithms, because this is the only case where the compiler has to
  2059. generate some runtime code. It is therefore only computations of this sort
  2060. that we will be studying in the remainder of this section.
  2061. Like we did for compile-time benchmarks, the methodology used to measure
  2062. runtime performance in Hana is data driven rather than analytical. In other
  2063. words, instead of trying to determine the complexity of an algorithm by
  2064. counting the number of basic operations it does as a function of the input
  2065. size, we simply take measurements for the most interesting cases and see how
  2066. it behaves. There are a couple of reasons for doing so. First, we do not
  2067. expect Hana's algorithms to be called on large inputs since those algorithms
  2068. work on heterogeneous sequences whose length must be known at compile-time.
  2069. For example, if you tried to call the `find_if` algorithm on a sequence of
  2070. 100k elements, your compiler would simply die while trying to generate the
  2071. code for this algorithm. Hence, algorithms can't be called on very large inputs
  2072. and the analytical approach then loses a lot of its attractiveness. Secondly,
  2073. processors have evolved into pretty complex beasts, and the actual performance
  2074. you'll be able to squeeze out is actually controlled by much more than the
  2075. mere number of steps your algorithm is doing. For example, bad cache behavior
  2076. or branch misprediction could turn a theoretically efficient algorithm into a
  2077. slowpoke, especially for small inputs. Since Hana causes a lot of unrolling to
  2078. happen, these factors must be considered even more carefully and any analytical
  2079. approach would probably only comfort us into thinking we're efficient. Instead,
  2080. we want hard data, and pretty charts to display it!
  2081. @note
  2082. Like for compile-time performance, we're forcing the evaluation of some Fusion
  2083. algorithms that are normally lazy. Again, depending on the complexity of the
  2084. computation, a lazy algorithm may cause substantially different code to be
  2085. generated or a different design to be used, for better or worse. Keep this
  2086. in mind when you look at these runtime benchmarks. If performance is absolutely
  2087. critical to your application, you should profile _before_ and _after_ switching
  2088. from Fusion to Hana. And let us know if Hana performs worse; we'll fix it!
  2089. There are a couple of different aspects we will want to benchmark. First, we
  2090. will obviously want to benchmark the execution time of the algorithms.
  2091. Secondly, because of the by-value semantics used throughout the library, we
  2092. will also want to make sure that the minimum amount of data is copied around.
  2093. Finally, we will want to make sure that using Hana does not cause too much
  2094. code bloat because of unrolling, as explained in the [section]
  2095. (@ref tutorial-algorithms-codegen) on algorithms.
  2096. Just like we studied only a couple of key algorithms for compile-time
  2097. performance, we will focus on the runtime performance of a few algorithms.
  2098. For each benchmarked aspect, we will compare the algorithm as implemented by
  2099. different libraries. Our goal is to always be at least as efficient as
  2100. Boost.Fusion, which is near from optimality in terms of runtime performance.
  2101. For comparison, we also show the same algorithm as executed on a runtime
  2102. sequence, and on a sequence whose length is known at compile-time but whose
  2103. `transform` algorithm does not use explicit loop unrolling. All the benchmarks
  2104. presented here are done in a _Release_ CMake configuration, which takes care
  2105. of passing the proper optimization flags (usually `-O3`). Let's start with the
  2106. following chart, which shows the execution time required to `transform`
  2107. different kinds of sequences:
  2108. <div class="benchmark-chart"
  2109. style="min-width: 310px; height: 400px; margin: 0 auto"
  2110. data-dataset="benchmark.transform.execute.json">
  2111. </div>
  2112. @note
  2113. Keep in mind that `fusion::transform` is usually lazy, and we're forcing its
  2114. evaluation for the purpose of benchmarking.
  2115. As you can see, Hana and Fusion are pretty much on the same line. `std::array`
  2116. is slightly slower for larger collections data sets, and `std::vector` is
  2117. noticeably slower for larger collections. Since we also want to look out for
  2118. code bloat, let's take a look at the size of the executable generated for the
  2119. exact same scenario:
  2120. <div class="benchmark-chart"
  2121. style="min-width: 310px; height: 400px; margin: 0 auto"
  2122. data-dataset="benchmark.transform.bloat.json">
  2123. </div>
  2124. As you can see, code bloat does not seem to be an issue, at least not one that
  2125. can be detected in micro benchmarks such as this one. Let's now take a look at
  2126. the `fold` algorithm, which is used very frequently:
  2127. <div class="benchmark-chart"
  2128. style="min-width: 310px; height: 400px; margin: 0 auto"
  2129. data-dataset="benchmark.fold_left.execute.json">
  2130. </div>
  2131. Here, you can see that everybody is performing pretty much the same, which
  2132. is a good sign that Hana is at least not screwing things up.
  2133. Again, let's look at the executable size:
  2134. <div class="benchmark-chart"
  2135. style="min-width: 310px; height: 400px; margin: 0 auto"
  2136. data-dataset="benchmark.fold_left.bloat.json">
  2137. </div>
  2138. Here again, the code size did not explode. So at least for moderate usages of
  2139. Hana (and Fusion for that matter, since they have the same problem), code
  2140. bloat should not be a major concern. The containers in the charts we just
  2141. presented contain randomly generated `int`s, which is cheap to copy around and
  2142. lends itself well to micro benchmarks. However, what happens when we chain
  2143. multiple algorithms on a container whose elements are expensive to copy? More
  2144. generally, the question is: when an algorithm is passed a temporary object,
  2145. does it seize the opportunity to avoid unnecessary copies? Consider:
  2146. @code{cpp}
  2147. auto xs = hana::make_tuple("some"s, "huge"s, "string"s);
  2148. // No copy of xs's elements should be made: they should only be moved around.
  2149. auto ys = hana::reverse(std::move(xs));
  2150. @endcode
  2151. To answer this question, we'll look at the chart generated when benchmarking
  2152. the above code for strings of about 1k characters. However, note that it does
  2153. not really make sense to benchmark this for standard library algorithms,
  2154. because they do not return containers.
  2155. <div class="benchmark-chart"
  2156. style="min-width: 310px; height: 400px; margin: 0 auto"
  2157. data-dataset="benchmark.reverse.move.json">
  2158. </div>
  2159. @note
  2160. Keep in mind that `fusion::reverse` is usually lazy, and we're forcing its
  2161. evaluation for the purpose of benchmarking.
  2162. As you can see, Hana is faster than Fusion, probably because of a more
  2163. consistent use of move semantics in the implementation. If we had not
  2164. provided a temporary container to `reverse`, no move could have been
  2165. performed by Hana and both libraries would have performed similarly:
  2166. <div class="benchmark-chart"
  2167. style="min-width: 310px; height: 400px; margin: 0 auto"
  2168. data-dataset="benchmark.reverse.nomove.json">
  2169. </div>
  2170. This concludes the section on runtime performance. Hopefully you are now
  2171. convinced that Hana was built for speed. Performance is important to us:
  2172. if you ever encounter a scenario where Hana causes bad code to be generated
  2173. (and the fault is not on the compiler), please open an [issue][Hana.issues]
  2174. so the problem can be addressed.
  2175. @section tutorial-ext Integration with external libraries
  2176. ------------------------------------------------------------------------------
  2177. Hana provides out-of-the-box integration with some existing libraries.
  2178. Specifically, this means that you can use some containers from these
  2179. libraries in Hana's algorithms by simply including the appropriate header
  2180. making the bridge between Hana and the external component. This can be
  2181. very useful for porting existing code from e.g. Fusion/MPL to Hana:
  2182. @snippet example/tutorial/ext/fusion_to_hana.cpp main
  2183. @note
  2184. - At this time, only adapters to use data types from other libraries inside Hana
  2185. are provided; adapters for the other way around (using Hana containers inside
  2186. other libraries) are not provided.
  2187. - The Fusion and MPL adapters are only guaranteed to work on the version of
  2188. Boost matching the version of Hana being used.
  2189. However, using external adapters has a couple of pitfalls. For example, after
  2190. a while using Hana, you might become used to comparing Hana tuples using the
  2191. normal comparison operators, or doing arithmetic with Hana `integral_constant`s.
  2192. Of course, nothing guarantees that these operators are defined for external
  2193. adapters too (and in general they won't be). Hence, you'll have to stick to
  2194. the functions provided by Hana that implement these operators. For example:
  2195. @code{cpp}
  2196. auto r = std::ratio<3, 4>{} + std::ratio<4, 5>{}; // error, the operator is not defined!
  2197. @endcode
  2198. Instead, you should use the following:
  2199. @snippet example/tutorial/ext/ratio_plus.cpp main
  2200. But sometimes, it's much worse. Some external components define operators, but
  2201. they don't necessarily have the same semantics as those from Hana. For example,
  2202. comparing two `std::tuple`s of different lengths will give an error when using
  2203. `operator==`:
  2204. @code{cpp}
  2205. std::make_tuple(1, 2, 3) == std::make_tuple(1, 2); // compiler error
  2206. @endcode
  2207. On the other hand, comparing Hana tuples of different lengths will just return
  2208. a false `IntegralConstant`:
  2209. @code{cpp}
  2210. hana::make_tuple(1, 2, 3) == hana::make_tuple(1, 2); // hana::false_c
  2211. @endcode
  2212. This is because `std::tuple` defines its own operators, and their semantics
  2213. are different from that of Hana's operators. The solution is to stick with
  2214. Hana's named functions instead of using operators when you know you'll have
  2215. to work with other libraries:
  2216. @code{cpp}
  2217. hana::equal(std::make_tuple(1, 2, 3), std::make_tuple(1, 2)); // hana::false_c
  2218. @endcode
  2219. When using external adapters, one should also be careful not to forget
  2220. including the proper bridge headers. For example, suppose I want to use
  2221. a Boost.MPL vector with Hana. I include the appropriate bridge header:
  2222. @snippet example/tutorial/ext/mpl_vector.cpp front
  2223. @note
  2224. The exact layout of these bridge headers is documented in the section about
  2225. [Header organization](@ref tutorial-header_organization).
  2226. Now, however, suppose that I use `mpl::size` to query the size of the vector
  2227. and then compare it to some value. I could also use `hana::length` and
  2228. everything would be fine, but bear with me for the sake of the example:
  2229. @snippet example/tutorial/ext/mpl_vector.cpp size
  2230. The reason why this breaks is that `mpl::size` returns a MPL IntegralConstant,
  2231. and Hana has no way of knowing about these unless you include the proper
  2232. bridge header. Hence, you should do the following instead:
  2233. @snippet example/tutorial/ext/mpl_vector.cpp size-fixed
  2234. The morale is that when working with external libraries, you have to be a bit
  2235. careful about what objects you are manipulating. The final pitfall is about
  2236. implementation limits in external libraries. Many older libraries have limits
  2237. regarding the maximum size of the heterogeneous containers that can be created
  2238. with them. For example, one may not create a Fusion list of more than
  2239. `FUSION_MAX_LIST_SIZE` elements in it. Obviously, these limits are inherited
  2240. by Hana and for example, trying to compute the permutations of a `fusion::list`
  2241. containing 5 elements (the resulting list would contain 120 elements) will
  2242. fail in a gruesome way:
  2243. @code{cpp}
  2244. auto list = fusion::make_list(1, 2, 3, 4, 5);
  2245. auto oh_jeez = hana::permutations(list); // probably won't make it
  2246. @endcode
  2247. Apart from the pitfalls explained in this section, using external adapters
  2248. should be just as straightforward as using normal Hana containers. Of course,
  2249. whenever possible, you should try to stick with Hana's containers because they
  2250. are usually more friendly to work with and are often more optimized.
  2251. @section tutorial-core Hana's core
  2252. ------------------------------------------------------------------------------
  2253. The goal of this section is to give a high-level overview of Hana's core.
  2254. This core is based on the notion of _tag_, which is borrowed from the
  2255. Boost.Fusion and Boost.MPL libraries but taken much further by Hana. These
  2256. tags are then used for several purposes, like algorithm customization,
  2257. documentation grouping, improving error messages and converting containers
  2258. into other containers. Because of its modular design, Hana can be extended
  2259. in a ad-hoc manner very easily. In fact, all the functionality of the library
  2260. is provided through an ad-hoc customization mechanism, which is explained here.
  2261. @subsection tutorial-core-tags Tags
  2262. Heterogeneous programming is basically programming with objects having
  2263. different types. However, it is clear that some families of objects, while
  2264. having different representations (C++ types), are strongly related. For
  2265. example, the `std::integral_constant<int, n>` types are different for each
  2266. different `n`, but conceptually they all represent the same thing; a
  2267. compile-time number. The fact that `std::integral_constant<int, 1>{}` and
  2268. `std::integral_constant<int, 2>{}` have different types is just a side effect
  2269. of the fact that we're using their type to encode the _value_ of these objects.
  2270. Indeed, when manipulating a sequence of `std::integral_constant<int, ...>`s,
  2271. chances are that you actually think of it as a homogeneous sequence of an
  2272. imaginary `integral_constant` type, disregarding the actual types of the
  2273. objects and pretending they are all just `integral_constant`s with different
  2274. values.
  2275. To reflect this reality, Hana provides _tags_ representing its heterogeneous
  2276. containers and other compile-time entities. For example, all of Hana's
  2277. `integral_constant<int, ...>`s have different types, but they all share
  2278. the same tag, `integral_constant_tag<int>`. This allows the programmer to
  2279. think in terms of that single type instead of trying to think in terms of the
  2280. actual types of the objects. Concretely, tags are implemented as empty `struct`s.
  2281. To make them stand out, Hana adopts the convention of naming these tags by
  2282. adding the `_tag` suffix.
  2283. @note
  2284. The tag of an object of type `T` can be obtained by using `tag_of<T>::%type`,
  2285. or equivalently `tag_of_t<T>`.
  2286. Tags are an extension to normal C++ types. Indeed, by default, the tag of a
  2287. type `T` is `T` itself, and the core of the library is designed to work in
  2288. those cases. For example, `hana::make` expects either a tag or an actual type;
  2289. if you send it a type `T`, it will do the logical thing and construct an
  2290. object of type `T` with the arguments you pass it. If you pass a tag to it,
  2291. however, you should specialize `make` for that tag and provide your own
  2292. implementation, as explained below. Because tags are an extension to usual
  2293. types, we end up mostly reasoning in terms of tags instead of usual types,
  2294. and the documentation sometimes uses the words _type_, _data type_ and _tag_
  2295. interchangeably.
  2296. @subsection tutorial-core-tag_dispatching Tag dispatching
  2297. Tag dispatching is a generic programming technique for picking the right
  2298. implementation of a function depending on the type of the arguments passed
  2299. to the function. The usual mechanism for overriding a function's behavior
  2300. is overloading. Unfortunately, this mechanism is not always convenient when
  2301. dealing with families of related types having different base templates, or
  2302. when the kind of template parameters is not known (is it a type or a non-type
  2303. template parameter?). For example, consider trying to overload a function for
  2304. all Boost.Fusion vectors:
  2305. @code{cpp}
  2306. template <typename ...T>
  2307. void function(boost::fusion::vector<T...> v) {
  2308. // whatever
  2309. }
  2310. @endcode
  2311. If you know Boost.Fusion, then you probably know that it won't work. This is
  2312. because Boost.Fusion vectors are not necessarily specializations of the
  2313. `boost::fusion::vector` template. Fusion vectors also exist in numbered
  2314. forms, which are all of different types:
  2315. @code{cpp}
  2316. boost::fusion::vector1<T>
  2317. boost::fusion::vector2<T, U>
  2318. boost::fusion::vector3<T, U, V>
  2319. ...
  2320. @endcode
  2321. This is an implementation detail required by the lack of variadic templates in
  2322. C++03 that leaks into the interface. This is unfortunate, but we need a way to
  2323. work around it. To do so, we use an infrastructure with three distinct
  2324. components:
  2325. 1. A metafunction associating a single tag to every type in a family of
  2326. related types. In Hana, this tag can be accessed using the `tag_of`
  2327. metafunction. Specifically, for any type `T`, `tag_of<T>::%type` is
  2328. the tag used to dispatch it.
  2329. 2. A function belonging to the public interface of the library, for which
  2330. we'd like to be able to provide a customized implementation. In Hana,
  2331. these functions are the algorithms associated to a concept, like
  2332. `transform` or `unpack`.
  2333. 3. An implementation for the function, parameterized with the tag(s) of the
  2334. argument(s) passed to the function. In Hana, this is usually done by having
  2335. a separate template called `xxx_impl` (for an interface function `xxx`)
  2336. with a nested `apply` static function, as will be shown below.
  2337. When the public interface function `xxx` is called, it will get the tag of the
  2338. argument(s) it wishes to dispatch the call on, and then forward the call to
  2339. the `xxx_impl` implementation associated to those tags. For example, let's
  2340. implement a basic setup for tag dispatching of a function that prints its
  2341. argument to a stream. First, we define the public interface function and the
  2342. implementation that can be specialized:
  2343. @snippet example/tutorial/tag_dispatching.cpp setup
  2344. Now, let's define a type that needs tag dispatching to customize the behavior
  2345. of `print`. While some C++14 examples exist, they are too complicated to show
  2346. in this tutorial and we will therefore use a C++03 tuple implemented as several
  2347. different types to illustrate the technique:
  2348. @snippet example/tutorial/tag_dispatching.cpp vector
  2349. The nested `using hana_tag = vector_tag;` part is a terse way of controling
  2350. the result of the `tag_of` metafunction, and hence the tag of the `vectorN`
  2351. type. This is explained in the reference for `tag_of`. Finally, if you wanted
  2352. to customize the behavior of the `print` function for all the `vectorN` types,
  2353. you would normally have to write something along the lines of
  2354. @snippet example/tutorial/tag_dispatching.cpp old_way
  2355. Now, with tag dispatching, you can rely on the `vectorN`s all sharing the same
  2356. tag and specialize only the `print_impl` struct instead:
  2357. @snippet example/tutorial/tag_dispatching.cpp customize
  2358. One upside is that all `vectorN`s can now be treated uniformly by the `print`
  2359. function, at the cost of some boilerplate when creating the data structure
  2360. (to specify the tag of each `vectorN`) and when creating the initial `print`
  2361. function (to setup the tag dispatching system with `print_impl`). There are
  2362. also other advantages to this technique, like the ability to check for
  2363. preconditions in the interface function without having to do it in each
  2364. custom implementation, which would be tedious:
  2365. @snippet example/tutorial/tag_dispatching.cpp preconditions
  2366. @note
  2367. Checking preconditions does not make much sense for a `print` function, but
  2368. consider for example a function to get the `n`th element of a sequence; you
  2369. might want to make sure that the index is not out-of-bounds.
  2370. This technique also makes it easier to provide interface functions as function
  2371. objects instead of normal overloaded functions, because only the interface
  2372. function itself must go through the trouble of defining a function object.
  2373. Function objects have several advantages over overloaded functions, like the
  2374. ability to be used in higher order algorithms or as variables:
  2375. @snippet example/tutorial/tag_dispatching.cpp function_objects
  2376. As you are probably aware of, being able to implement an algorithm for many
  2377. types at the same time is tremendously useful (that's precisely the goal of
  2378. C++ templates!). However, even more useful is the ability to implement an
  2379. algorithm for many types _that satisfy some condition_. C++ templates are
  2380. currently missing this ability to constrain their template parameters, but a
  2381. language feature called [concepts][C++17.clite] is being rolled out with the
  2382. goal of addressing this issue.
  2383. With something similar in mind, Hana's algorithms support an additional layer
  2384. of tag-dispatching to what was explained above. This layer allows us to
  2385. "specialize" an algorithm for all types that satisfy some predicate. For
  2386. example, let's say we wanted to implement the `print` function above for all
  2387. types that represent some kind of sequence. Right now, we wouldn't have an
  2388. easy way to do this. However, the tag dispatching for Hana's algorithms is
  2389. set up slightly differently than what was shown above, and we could hence
  2390. write the following:
  2391. @snippet example/tutorial/tag_dispatching.cpp customize-when
  2392. where `Tag represents some kind of sequence` would only need to be a boolean
  2393. expression representing whether `Tag` is a sequence. We'll see how such
  2394. predicates can be created in the next section, but for now let's assume that
  2395. it _just works_. Without going into the details of how this tag-dispatching is
  2396. set up, the above specialization will only be picked up when the predicate is
  2397. satisfied, and if no better match can be found. Hence, for example, if our
  2398. `vector_tag` was to satisfy the predicate, our initial implementation for
  2399. `vector_tag` would still be preferred over the `hana::when`-based specialization,
  2400. because it represents a better match. In general, any specialization (whether
  2401. explicit or partial) _not_ using `hana::when` will be preferred over a
  2402. specialization using `hana::when`, which was designed to be as unsurprising
  2403. as possible from a user point of view. This covers pretty much all there's
  2404. to say about tag-dispatching in Hana. The next section will explain how we
  2405. can create C++ concepts for metaprogramming, which could then be used in
  2406. conjunction with `hana::when` to achieve a great deal of expressiveness.
  2407. @subsection tutorial-core-concepts Emulation of C++ concepts
  2408. The implementation of concepts in Hana is very simple. At its heart, a concept
  2409. is just a template `struct` that inherits from a boolean `integral_constant`
  2410. representing whether the given type is a _model_ of the concept:
  2411. @code{cpp}
  2412. template <typename T>
  2413. struct Concept
  2414. : hana::integral_constant<bool, whether T models Concept>
  2415. { };
  2416. @endcode
  2417. Then, one can test whether a type `T` is a model of `Concept` by looking at
  2418. `Concept<T>::%value`. Simple enough, right? Now, while the way one might
  2419. implement the check does not have to be anything specific as far as Hana
  2420. is concerned, the rest of this section will explain how it is usually done
  2421. in Hana, and how it interacts with tag dispatching. You should then be able
  2422. to define your own concepts if you so desire, or at least to understand better
  2423. how Hana works internally.
  2424. Usually, a concept defined by Hana will require that any model implements some
  2425. tag-dispatched functions. For example, the `Foldable` concept requires that
  2426. any model defines at least one of `hana::unpack` and `hana::fold_left`. Of
  2427. course, concepts usually also define semantic requirements (called laws) that
  2428. must be satisfied by their models, but these laws are not (and couldn't be)
  2429. checked by the concept. But how do we check that some functions are properly
  2430. implemented? For this, we'll have to slightly modify the way we defined
  2431. tag-dispatched methods as shown in the previous section. Let's go back to
  2432. our `print` example and try to define a `Printable` concept for those objects
  2433. that can be `print`ed. Our end goal is to have a template struct such as
  2434. @code{cpp}
  2435. template <typename T>
  2436. struct Printable
  2437. : hana::integral_constant<bool, whether print_impl<tag of T> is defined>
  2438. { };
  2439. @endcode
  2440. To know whether `print_impl<...>` has been defined, we'll modify `print_impl`
  2441. so that it inherits from a special base class when it is not overridden, and
  2442. we'll simply check whether `print_impl<T>` inherits from that base class:
  2443. @snippet example/tutorial/concepts.cpp special_base_class
  2444. Of course, when we specialize `print_impl` with a custom type, we don't
  2445. inherit from that `special_base_class` type:
  2446. @snippet example/tutorial/concepts.cpp special_base_class_customize
  2447. As you can see, `Printable<T>` really only checks whether the `print_impl<T>`
  2448. struct was specialized by a custom type. In particular, it does not even check
  2449. whether the nested `::%apply` function is defined or if it is syntactically
  2450. valid. It is assumed that if one specializes `print_impl` for a custom type,
  2451. the nested `::%apply` function exists and is correct. If it is not, a compilation
  2452. error will be triggered when one tries to call `print` on an object of that type.
  2453. Concepts in Hana make the same assumptions.
  2454. Since this pattern of inheriting from a special base class is quite abundant
  2455. in Hana, the library provides a dummy type called `hana::default_` that can be
  2456. used in place of `special_base_class`. Then, instead of using `std::is_base_of`,
  2457. one can use `hana::is_default`, which looks nicer. With this syntactic sugar,
  2458. the code now becomes:
  2459. @snippet example/tutorial/concepts.cpp actual
  2460. This is all that there's to know about the interaction between tag-dispatched
  2461. functions and concepts. However, some concepts in Hana do not rely solely on
  2462. the definition of specific tag-dispatched functions to determine if a type is
  2463. a model of the concept. This can happen when a concept merely introduces
  2464. semantic guarantees through laws and refined concepts, but no additional
  2465. syntactic requirements. Defining such a concept can be useful for several
  2466. reasons. First, it sometimes happen that an algorithm can be implemented
  2467. more efficiently if we can assume some semantic guarantees X or Y, so we
  2468. might create a concept to enforce those guarantees. Secondly, it is sometimes
  2469. possible to automatically define the models for several concepts when we have
  2470. additional semantic guarantees, which saves the user the trouble of defining
  2471. those models manually. For example, this is the case of the `Sequence` concept,
  2472. which basically adds semantic guarantees to `Iterable` and `Foldable`, and in
  2473. turn allows us to define the models for a myriad of concepts ranging from
  2474. `Comparable` to `Monad`.
  2475. For these concepts, it is usually necessary to specialize the corresponding
  2476. template struct in the `boost::hana` namespace to provide a model for a custom
  2477. type. Doing so is like providing a seal saying that the semantic guarantees
  2478. required by the concept are respected by the custom type. The concepts that
  2479. require being explicitly specialized will document that fact. So that's it!
  2480. This is all that there's to know about concepts in Hana, which ends this
  2481. section about the core of Hana.
  2482. @section tutorial-header_organization Header organization
  2483. ------------------------------------------------------------------------------
  2484. The library is designed to be modular while keeping the number of headers that
  2485. must be included to get basic functionality reasonably low. The structure of
  2486. the library was also intentionally kept simple, because we all love simplicity.
  2487. What follows is a general overview of the header organization. A list of all
  2488. the headers provided by the library is also available in the panel on the left
  2489. (under the [Headers](files.html) label) in case you need more details.
  2490. - `boost/hana.hpp`\n
  2491. This is the master header of the library, which includes the whole public
  2492. interface of the library. Note that external adapters, experimental features
  2493. and implementation details are not included by this header, however, since
  2494. some of them require additional dependencies.
  2495. - `boost/hana/`\n
  2496. This is the main directory of the library containing the definitions of
  2497. everything provided by the library. Each algorithm and container provided
  2498. by the library has its own header. For a container or an algorithm named
  2499. `XXX`, the corresponding header is `boost/hana/XXX.hpp`.
  2500. - `boost/hana/concept/`\n
  2501. This subdirectory contains the definition of Hana's concepts. These
  2502. headers provide a way to check whether an object is a model of the
  2503. corresponding concept, and they sometimes also provide default
  2504. implementations for other related concepts, which are documented
  2505. on a per-concept basis. They also include all the algorithms associated
  2506. to that concept.
  2507. - `boost/hana/core/`\n
  2508. This subdirectory contains the machinery for tag dispatching and other
  2509. related utilities like `make` and `to`.
  2510. - `boost/hana/fwd/`\n
  2511. This subdirectory contains the forward declaration of everything in the
  2512. library. It is essentially a mirror of the `boost/hana/` directory, except
  2513. all the headers contain only forward declarations and documentation. For
  2514. example, to include the `hana::tuple` container, one can use the
  2515. `boost/hana/tuple.hpp` header. However, if one only wants the
  2516. forward declaration of that container, the `boost/hana/fwd/tuple.hpp`
  2517. header can be used instead. Note that forward declarations for headers
  2518. in `boost/hana/ext/` and `boost/hana/functional/` are not provided.
  2519. - `boost/hana/functional/`\n
  2520. This subdirectory contains various function objects that are often useful,
  2521. but that do not necessarily belong to a concept.
  2522. - `boost/hana/ext/`\n
  2523. This directory contains adapters for external libraries. For a component
  2524. named `xxx` in a namespace `ns`, the external adapter lives in the
  2525. `boost/hana/ext/ns/xxx.hpp` header. For example, the external adapter
  2526. for `std::tuple` lives in the `boost/hana/ext/std/tuple.hpp` header,
  2527. while the external adapter for `boost::mpl::vector` is in
  2528. `boost/hana/ext/boost/mpl/vector.hpp`.
  2529. Note that only the strict minimum required to adapt the external components
  2530. is included in these headers (e.g. a forward declaration). This means that
  2531. the definition of the external component should still be included when one
  2532. wants to use it. For example:
  2533. @snippet example/tutorial/include_ext.cpp main
  2534. - `boost/hana/experimental/`\n
  2535. This directory contains experimental features that may or may not make it
  2536. into the library at some point, but that were deemed useful enough to be
  2537. made available to the public. Features in this subdirectory reside in the
  2538. `hana::experimental` namespace. Also, do not expect these features to be
  2539. stable; they may be moved, renamed, changed or removed between releases of
  2540. the library. These features may also require additional external dependencies;
  2541. each feature documents the additional dependencies it requires, if any.
  2542. Because of the potential additional dependencies, these headers are also
  2543. not included by the master header of the library.
  2544. - `boost/hana/detail/`\n
  2545. This directory contains utilities required internally. Nothing in `detail/`
  2546. is guaranteed to be stable, so you should not use it.
  2547. @section tutorial-conclusion Conclusion
  2548. ------------------------------------------------------------------------------
  2549. You now have everything you need to start using the library. From this point
  2550. forward, mastering the library is only a matter of understanding how to use
  2551. the general purpose concepts and containers provided with it, which is best
  2552. done by looking at the reference documentation. At some point, you will
  2553. probably also want to create your own concepts and data types that fit your
  2554. needs better; go ahead, the library was designed to be used that way.
  2555. @subsection tutorial-conclusion-warning Fair warning: functional programming ahead
  2556. Programming with heterogeneous objects is inherently functional -- since it is
  2557. impossible to modify the type of an object, a new object must be introduced
  2558. instead, which rules out mutation. Unlike previous metaprogramming libraries
  2559. whose design was modeled on the STL, Hana uses a functional style of
  2560. programming which is the source for a good portion of its expressiveness.
  2561. However, as a result, many concepts presented in the reference will be
  2562. unfamiliar to C++ programmers without a knowledge of functional programming.
  2563. The reference attempts to make these concepts approachable by using intuition
  2564. whenever possible, but bear in mind that the highest rewards are usually the
  2565. fruit of some effort.
  2566. @subsection tutorial-conclusion-related_material Related material
  2567. Through the years, I have produced some material about Hana and metaprogramming
  2568. more generally. You may find some of it useful:
  2569. - Keynote on metaprogramming at [Meeting C++][] 2016 ([slides](http://ldionne.com/meetingcpp-2016)/[video](https://youtu.be/X_p9X5RzBJE))
  2570. - Talk on advanced metaprogramming techniques used in Hana at [C++Now][] 2016 ([slides](http://ldionne.com/cppnow-2016-metaprogramming-for-the-brave)/[video](https://youtu.be/UXwWXHrvTug))
  2571. - Introduction to metaprogramming with Hana at [C++Now][] 2016 ([slides](http://ldionne.com/cppnow-2016-metaprogramming-for-dummies)/[video](https://youtu.be/a1doqFAumCk))
  2572. - Talk on the [MPL11][] library at [C++Now][] 2014. This is how Hana started out. ([slides](http://ldionne.com/mpl11-cppnow-2014)/[video](https://youtu.be/8c0aWLuEO0Y))
  2573. - My bachelor's thesis was a formalization of C++ metaprogramming using category
  2574. theory. The thesis is available [here](https://github.com/ldionne/hana-thesis/blob/gh-pages/main.pdf),
  2575. and the slides of a related presentation are available [here](http://ldionne.com/hana-thesis).
  2576. Unfortunately, both are in french only.
  2577. The complete list of talks I've done on Hana and metaprogramming is [here][ldionne.talks].
  2578. There is also an unofficial translation of Hana's documentation to Chinese
  2579. available [here](https://github.com/freezestudio/hana.zh).
  2580. @subsection tutorial-conclusion-projects_using_hana Projects using Hana
  2581. There is a growing number of projects using Hana. It can be useful to look
  2582. at them to get a sense of how to best use the library. Here's a few of those
  2583. projects ([open an issue][Hana.issues] if you want your project to be listed
  2584. here):
  2585. - [Dyno](https://github.com/ldionne/dyno): A policy-based type erasure library.
  2586. Uses Hana for vtable generation and concept map emulation under the hood.
  2587. - [yap](https://github.com/tzlaine/yap): An expression template library built
  2588. on top of Hana.
  2589. - [NBDL](https://github.com/ricejasonf/nbdl): Library for managing application
  2590. state across network. Uses Hana for some things under the hood.
  2591. - [ECST](https://github.com/SuperV1234/ecst): An experimental multithreaded
  2592. compile-time entity-component system using Hana under the hood for a few
  2593. things.
  2594. This finishes the tutorial part of the documentation. I hope you enjoy using
  2595. the library, and please consider [contributing][Hana.contributing] to make it
  2596. even better!
  2597. -- Louis
  2598. @section tutorial-reference Using the reference
  2599. ------------------------------------------------------------------------------
  2600. As for most generic libraries, algorithms in Hana are documented by the
  2601. concept to which they belong (`Foldable`, `Iterable`, `Searchable`, `Sequence`,
  2602. etc...). The different containers are then documented on their own page, and
  2603. the concepts that they model are documented there. The concepts modeled by
  2604. some container defines what algorithms can be used with such a container.
  2605. More specifically, the structure of the reference (available in the menu to
  2606. the left) goes as follow:
  2607. - @ref group-core \n
  2608. Documentation for the core module, which contains everything needed to
  2609. create concepts, data types and related utilities. This is relevant
  2610. if you need to extend the library, but otherwise you can probably
  2611. ignore this.
  2612. - @ref group-concepts \n
  2613. Documentation for all the concepts provided with the library. Each concept:
  2614. - Documents which functions must be implemented absolutely in order to
  2615. model that concept. The set of functions that must be provided is called
  2616. a _minimal complete definition_.
  2617. - Documents semantic constraints that any model of that concept must satisfy.
  2618. These constraints are usually called laws and they are expressed in a
  2619. semi-formal mathematical language. Of course, those laws can't be checked
  2620. automatically but you should still make sure you satisfy them.
  2621. - Documents the concept(s) it refines, if any. Sometimes, a concept is
  2622. powerful enough to provide a model of a concept it refines, or at least
  2623. the implementation for some of its associated functions. When this is the
  2624. case, the concept will document which functions of the refined concept it
  2625. provides, and how it does so. Also, it is sometimes possible that the
  2626. model for a refined concept is unique, in which case it can be provided
  2627. automatically. When this happens, it will be documented but you don't have
  2628. to do anything special to get that model.
  2629. - @ref group-datatypes \n
  2630. Documentation for all the data structures provided with the library. Each
  2631. data structure documents the concept(s) it models, and how it does so. It
  2632. also documents the methods tied to it but not to any concept, for example
  2633. `maybe` for `optional`.
  2634. - @ref group-functional \n
  2635. General purpose function objects that are generally useful in a purely
  2636. functional setting. These are currently not tied to any concept or container.
  2637. - @ref group-ext \n
  2638. Documentation for all the adapters for external libraries. These adapters
  2639. are documented as if they were native types provided by Hana, but obviously
  2640. Hana only provides the compatibility layer between them and the library.
  2641. - @ref group-config \n
  2642. Macros that can be used to tweak the global behavior of the library.
  2643. - @ref group-assertions \n
  2644. Macros to perform various types of assertions.
  2645. - [<b>Alphabetical index</b>](functions.html)\n
  2646. Alphabetical index of everything provided in the library.
  2647. - [<b>Headers</b>](files.html)\n
  2648. A list of all the headers provided by the library.
  2649. - @ref group-details \n
  2650. Implementation details; don't go there. Anything not documented at all or
  2651. documented in this group is not guaranteed to be stable.
  2652. After you get to know Hana a bit better, it will probably happen that you just
  2653. want to find the reference for a precise function, concept or container. If
  2654. you know the name of what you're looking for, you can use the _search_ box
  2655. located in the upper right corner of any page of the documentation. My
  2656. personal experience is that this is by far the quickest way of finding
  2657. what you want when you already know its name.
  2658. @subsection tutorial-reference-signatures Function signatures
  2659. As you will see in the reference, several functions provide signatures
  2660. documented in a semi-formal mathematical language. We are in the process
  2661. of documenting all functions in this way, but this may take a while. The
  2662. notation used is the usual mathematical notation for defining functions.
  2663. Specifically, a function `Return f(Arg1, ..., ArgN);` can be defined
  2664. equivalently using mathematical notation as
  2665. @f[
  2666. \mathtt{f} : \mathtt{Arg}_1 \times \dots \times \mathtt{Arg}_n
  2667. \to \mathtt{Return}
  2668. @f]
  2669. However, instead of documenting the actual argument and return types of
  2670. functions, those signatures are written in terms of argument and return tags.
  2671. This is done because of the heterogeneous setting, where the actual type of
  2672. an object is usually pretty meaningless and does not help to reason about
  2673. what's being returned or taken by a function. For example, instead of
  2674. documenting the `equal` function for `integral_constant`s as
  2675. @f[
  2676. \mathtt{equal} : \mathtt{integral\_constant<T, n>} \times
  2677. \mathtt{integral\_constant<T, m>}
  2678. \to \mathtt{integral\_constant<bool, n == m>}
  2679. @f]
  2680. which is not really helpful (as it really presents nothing but the
  2681. implementation), it is instead documented using `integral_constant_tag`,
  2682. which acts as the "type" of all `integral_constant`s. Note that since `equal`
  2683. is part of the `Comparable` concept, it is not _actually_ documented for
  2684. `hana::integral_constant` specifically, but the idea is there:
  2685. @f[
  2686. \mathtt{equal} : \mathtt{integral\_constant\_tag<T>} \times
  2687. \mathtt{integral\_constant\_tag<T>}
  2688. \to \mathtt{integral\_constant\_tag<bool>}
  2689. @f]
  2690. This clearly conveys the intention that comparing two `integral_constant`s
  2691. gives back another `integral_constant` holding a `bool`. In general, this
  2692. abstraction of the actual representation of objects makes it possible for
  2693. us to reason in a high level manner about functions, even though their
  2694. actual return and argument types are heterogeneous and not helpful. Finally,
  2695. most functions expect container elements to have some properties. For example,
  2696. this is the case of the `sort` algorithm, which obviously requires the
  2697. container elements to be `Orderable`. Normally, we would write the signature
  2698. for the non-predicated version of `sort` as
  2699. @f[
  2700. \mathtt{sort} : \mathtt{S} \to \mathtt{S} \\
  2701. \text{where S is a Sequence}
  2702. @f]
  2703. However, this fails to express the requirement that the contents of `S` are
  2704. `Orderable`. To express this, we use the following notation:
  2705. @f[
  2706. \mathtt{sort} : \mathtt{S(T)} \to \mathtt{S(T)} \\
  2707. \text{where S is a Sequence and T is Orderable}
  2708. @f]
  2709. One way to see this is to pretend that `S`, the sequence tag, is actually
  2710. parameterized by the tag of the sequence's elements, `T`. We're also pretending
  2711. that the elements all have the same tag `T`, which is not the case in general.
  2712. Now, by stating that `T` must be `Orderable`, we're expressing the fact that
  2713. the sequence's elements must be `Orderable`. This notation is used in different
  2714. flavors to express different kinds of requirements. For example, the
  2715. `cartesian_product` algorithm takes a sequence of sequences and returns the
  2716. cartesian product of those sequences as a sequence of sequences. Using our
  2717. notation, this can be conveyed very easily:
  2718. @f[
  2719. \mathtt{cartesian\_product} : \mathtt{S(S(T))} \to \mathtt{S(S(T))} \\
  2720. \text{where S is a Sequence}
  2721. @f]
  2722. @section tutorial-acknowledgements Acknowledgements
  2723. ------------------------------------------------------------------------------
  2724. I'd like to thank the following persons and organizations for contributing to
  2725. Hana in one way or another:
  2726. - Zach Laine and Matt Calabrese for the original idea of using function call
  2727. syntax to do type-level computations, as presented in their BoostCon
  2728. [presentation][video.inst_must_go] ([slides 1][slides.inst_must_go1])
  2729. ([slides 2][slides.inst_must_go2]).
  2730. - Joel Falcou for mentoring me two consecutive years during my work on Hana
  2731. as part of the [Google Summer of Code][GSoC] program, Niall Douglas for
  2732. being the GSoC admin for Boost and helping me get in the program, and
  2733. finally Google for their awesome GSoC program.
  2734. - The [Boost Steering committee][Boost.Steering] for unlocking a grant for me
  2735. to work on Hana in the winter of 2015, as an extension to the previous
  2736. year's GSoC.
  2737. - Several [C++Now][] attendees and members of the [Boost mailing list]
  2738. [Boost.Devel] for insightful conversations, comments and questions
  2739. about the project.
  2740. @section tutorial-glossary Glossary
  2741. ------------------------------------------------------------------------------
  2742. The reference documentation uses a couple of terms that are specific to this
  2743. library. Also, a simplified implementation of functions is sometimes provided
  2744. in pseudo-code, the actual implementation sometimes being slightly hard to
  2745. understand. This section defines terms used in the reference and in the
  2746. pseudo-code used to describe some functions.
  2747. @anchor tutorial-glossary-forwarded
  2748. #### `forwarded(x)`
  2749. Means that the object is forwarded optimally. This means that if `x` is a
  2750. parameter, it is `std::forward`ed, and if it is a captured variable, it is
  2751. moved from whenever the enclosing lambda is an rvalue.
  2752. Also note that when `x` can be moved from, the statement `return forwarded(x);`
  2753. in a function with `decltype(auto)` does not mean that an rvalue reference to
  2754. `x` will be returned, which would create a dangling reference. Rather, it
  2755. means that `x` is returned by value, the value being constructed with the
  2756. `std::forward`ed `x`.
  2757. @anchor tutorial-glossary-perfect_capture
  2758. #### `perfect-capture`
  2759. This is used in lambdas to signify that the captured variables are
  2760. initialized using perfect forwarding, as if `[x(forwarded(x))...]() { }`
  2761. had been used.
  2762. @anchor tutorial-glossary-tag_dispatched
  2763. #### `tag-dispatched`
  2764. This means that the documented function uses [tag dispatching]
  2765. (@ref tutorial-core-tag_dispatching), and hence the exact
  2766. implementation depends on the model of the concept associated
  2767. to the function.
  2768. @anchor tutorial-glossary-implementation_defined
  2769. #### `implementation-defined`
  2770. This expresses the fact that the exact implementation of an entity (usually a
  2771. type) should not be relied upon by users. In particular, this means that one
  2772. can not assume anything beyond what is written explicitly in the documentation.
  2773. Usually, the concepts satisfied by an implementation-defined entity will be
  2774. documented, because one could otherwise do nothing with it. Concretely,
  2775. assuming too much about an implementation-defined entity will probably
  2776. not kill you, but it will very probably break your code when you update
  2777. to a newer version of Hana.
  2778. @section tutorial-rationales Rationales/FAQ
  2779. ------------------------------------------------------------------------------
  2780. This section documents the rationale for some design choices. It also serves
  2781. as a FAQ for some (not so) frequently asked questions. If you think something
  2782. should be added to this list, open a GitHub issue and we'll consider either
  2783. improving the documentation or adding the question here.
  2784. @subsection tutorial-rationales-dependencies Why restrict usage of external dependencies?
  2785. There are several reasons for doing so. First, Hana is a very fundamental
  2786. library; we are basically reimplementing the core language and the standard
  2787. library with support for heterogeneous types. When going through the code,
  2788. one quickly realizes that other libraries are rarely needed, and that almost
  2789. everything has to be implemented from scratch. Also, since Hana is very
  2790. fundamental, there is even more incentive for keeping the dependencies
  2791. minimal, because those dependencies will be handed down to the users.
  2792. Regarding the minimal reliance on Boost in particular, one big argument
  2793. for using it is portability. However, as a cutting edge library, Hana only
  2794. targets very recent compilers. Hence, we can afford to depend on modern
  2795. constructs and the portability given to us by using Boost would mostly
  2796. represent dead weight.
  2797. @subsection tutorial-rationales-iterators Why no iterators?
  2798. Iterator based designs have their own merits, but they are also known to
  2799. reduce the composability of algorithms. Furthermore, the context of
  2800. heterogeneous programming brings a lot of points that make iterators much
  2801. less interesting. For example, incrementing an iterator would have to return
  2802. a new iterator with a different type, because the type of the new object it
  2803. is pointing to in the sequence might be different. It also turns out that
  2804. implementing most algorithms in terms of iterators leads to a worse
  2805. compile-time performance, simply because the execution model of metaprogramming
  2806. (using the compiler as an interpreter) is so different from the runtime
  2807. execution model of C++ (a processor accessing contiguous memory).
  2808. @subsection tutorial-rationales-container_representation Why leave some container's representation implementation-defined?
  2809. First, it gives much more wiggle room for the implementation to perform
  2810. compile-time and runtime optimizations by using clever representations for
  2811. specific containers. For example, a tuple containing homogeneous objects of
  2812. type `T` could be implemented as an array of type `T` instead, which is more
  2813. efficient at compile-time. Secondly, and most importantly, it turns out that
  2814. knowing the type of a _heterogeneous_ container is not as useful as you would
  2815. think. Indeed, in the context of heterogeneous programming, the type of the
  2816. object returned by a computation is usually part of the computation too. In
  2817. other words, there is no way to know the type of the object returned by an
  2818. algorithm without actually performing the algorithm. For example, consider
  2819. the `find_if` algorithm:
  2820. @snippet example/tutorial/rationale.container.cpp hana
  2821. If the predicate is satisfied for some element of the tuple, result will be
  2822. equal to `just(x)`. Otherwise, `result` will be equal to `nothing`. However,
  2823. the `nothing`ness of the result is known at compile-time, which requires
  2824. `just(x)` and `nothing` to have different types. Now, say you wanted to
  2825. explicitly write the type of the result:
  2826. @snippet example/tutorial/rationale.container.cpp hana-explicit
  2827. In order to possess the knowledge of what `some_type` is, you would need to
  2828. actually perform the algorithm, because `some_type` depends on whether the
  2829. predicate is satisfied or not for some element in the container. In other
  2830. words, if you were able to write the above, then you would already know what
  2831. the result of the algorithm is and you would not need to perform the algorithm
  2832. in the first place. In Boost.Fusion, this problem is addressed by having a
  2833. separate `result_of` namespace, which contains a metafunction computing the
  2834. result type of any algorithm given the types of the arguments passed to it.
  2835. For example, the above example could be rewritten with Fusion as:
  2836. @snippet example/tutorial/rationale.container.cpp fusion
  2837. Notice that we're basically doing the computation twice; once in the `result_of`
  2838. namespace and once in the normal `fusion` namespace, which is highly redundant.
  2839. Before the days of `auto` and `decltype`, such techniques were necessary to
  2840. perform heterogeneous computations. However, since the advent of modern C++,
  2841. the need for explicit return types in the context of heterogeneous programming
  2842. is largely obsolete, and knowing the actual type of containers is usually not
  2843. that useful.
  2844. @subsection tutorial-rationales-why_Hana Why Hana?
  2845. No, it isn't the name of my girlfriend! I just needed a short and good looking
  2846. name that people would easily remember, and Hana came up. It also came to my
  2847. attention that Hana means _flower_ in Japanese, and _one_ in Korean. Since
  2848. Hana is pretty and it unifies type-level and heterogeneous programming under
  2849. a single paradigm, the name appears to be quite well chosen in retrospect :-).
  2850. @subsection tutorial-rationales-tuple Why define our own tuple?
  2851. Since Hana defines a lot of algorithms on tuples, a possible way to go would
  2852. have been to simply use `std::tuple` and provide the algorithms only, instead
  2853. of also providing our own tuple. The reason for providing our own tuple is
  2854. principally performance. Indeed, all the `std::tuple` implementations tested
  2855. so far have a very bad compile-time performance. Also, to get truly amazing
  2856. compile-time performance, we need to take advantage of the tuple's internal
  2857. representation in some algorithms, which requires defining our own. Finally,
  2858. some sugar like `operator[]` could not be provided if we were using a
  2859. `std::tuple`, since that operator must be defined as a member function.
  2860. @subsection tutorial-rationales-naming How are names chosen?
  2861. When deciding upon a name `X`, I try to balance the following things
  2862. (in no specific order):
  2863. - How idiomatic is `X` in C++?
  2864. - How idiomatic is `X` in the rest of the programming world?
  2865. - How good of a name `X` _actually is_, regardless of historical reasons
  2866. - How do I, as the library author, feel about `X`
  2867. - How do users of the library feel about `X`
  2868. - Are there technical reasons not to use `X`, like name clashes or names
  2869. reserved by the standard
  2870. Of course, good naming is and will always be hard. Names are and will always
  2871. be tainted by the author's own bias. Still, I try to choose names in a
  2872. reasonable manner.
  2873. @subsection tutorial-rationales-parameters How is the parameter order decided?
  2874. Unlike naming, which is fairly subjective, the order of the parameters of a
  2875. function is usually pretty straightforward to determine. Basically, the rule
  2876. of thumb is "the container goes first". It has always been this way in Fusion
  2877. and MPL, and this is intuitive for most C++ programmers. Also, in higher-order
  2878. algorithms, I try to put the function parameter last, so that multi-line
  2879. lambdas look nice:
  2880. @code{cpp}
  2881. algorithm(container, [](auto x) {
  2882. return ...;
  2883. });
  2884. // is nicer than
  2885. algorithm([](auto x) {
  2886. return ...;
  2887. }, container);
  2888. @endcode
  2889. @subsection tutorial-rationales-tag_dispatching Why tag dispatching?
  2890. There are several different techniques we could have used to provide
  2891. customization points in the library, and tag-dispatching was chosen. Why?
  2892. First, I wanted a two-layer dispatching system because this allows functions
  2893. from the first layer (the ones that are called by users) to actually be
  2894. function objects, which allows passing them to higher-order algorithms.
  2895. Using a dispatching system with two layers also allows adding some
  2896. compile-time sanity checks to the first layer, which improves error messages.
  2897. Now, tag-dispatching was chosen over other techniques with two layers for a
  2898. couple of reasons. First, having to explicitly state how some tag is a model
  2899. of a concept gives the responsibility of making sure that the semantic
  2900. requirements of the concept are respected to the user. Secondly, when checking
  2901. whether a type is a model of some concept, we basically check that some key
  2902. functions are implemented. In particular, we check that the functions from the
  2903. minimal complete definition of that concept are implemented. For example,
  2904. `Iterable<T>` checks whether the `is_empty`, `at` and `drop_front` functions
  2905. implemented for `T`. However, the only way to detect this without
  2906. tag-dispatching is to basically check whether the following expressions
  2907. are valid in a SFINAE-able context:
  2908. @code{cpp}
  2909. implementation_of_at(std::declval<T>(), std::declval<N>())
  2910. implementation_of_is_empty(std::declval<T>())
  2911. implementation_of_drop_front(std::declval<T>())
  2912. @endcode
  2913. Unfortunately, this requires actually doing the algorithms, which might either
  2914. trigger a hard compile-time error or hurt compile-time performance. Also, this
  2915. requires picking an arbitrary index `N` to call `at` with: what if the `Iterable`
  2916. is empty? With tag dispatching, we can just ask whether `at_impl<T>`,
  2917. `is_empty_impl<T>` and `drop_front_impl<T>` are defined, and nothing happens
  2918. until we actually call their nested `::%apply` function.
  2919. @subsection tutorial-rationales-zip_longest Why not provide zip_longest?
  2920. It would require either (1) padding the shortest sequences with an arbitrary
  2921. object, or (2) padding the shortest sequences with an object provided by the
  2922. user when calling `zip_longest`. Since there is no requirement that all the
  2923. zipped sequences have elements of similar types, there is no way to provide a
  2924. single consistent padding object in all cases. A tuple of padding objects
  2925. should be provided, but I find it perhaps too complicated to be worth it for
  2926. now. If you need this functionality, open a GitHub issue.
  2927. @subsection tutorial-rationales-concepts Why aren't concepts constexpr functions?
  2928. Since the C++ concept proposal maps concepts to boolean `constexpr` functions,
  2929. it would make sense that Hana defines its concepts as such too, instead of as
  2930. structs with a nested `::%value`. Indeed, this was the first choice, but it
  2931. had to be revised because template functions have one limitation that makes
  2932. them less flexible. Specifically, a template function can't be passed to a
  2933. higher-order metafunction. In other words, it is not possible to write the
  2934. following
  2935. @code{cpp}
  2936. template <??? Concept>
  2937. struct some_metafunction {
  2938. // ...
  2939. };
  2940. @endcode
  2941. This sort of code is very useful in some contexts, such as checking whether
  2942. two types have a common embedding modeling a concept:
  2943. @code{cpp}
  2944. template <??? Concept, typename T, typename U>
  2945. struct have_common_embedding {
  2946. // whether T and U both model Concept, and share a common type that also models Concept
  2947. };
  2948. @endcode
  2949. With concepts as boolean `constexpr` functions, this can't be written
  2950. generically. When concepts are just template structs, however, we can
  2951. use template template parameters:
  2952. @code{cpp}
  2953. template <template <typename ...> class Concept, typename T, typename U>
  2954. struct have_common_embedding {
  2955. // whether T and U both model Concept, and share a common type that also models Concept
  2956. };
  2957. @endcode
  2958. @section tutorial-appendix-constexpr Appendix I: Advanced constexpr
  2959. ------------------------------------------------------------------------------
  2960. In C++, the border between compile-time and runtime is hazy, a fact that is
  2961. even more true with the introduction of [generalized constant expressions]
  2962. [C++14.gconstexpr] in C++14. However, being able to manipulate heterogeneous
  2963. objects is all about understanding that border and then crossing it at one's
  2964. will. The goal of this section is to set things straight with `constexpr`; to
  2965. understand which problems it can solve and which ones it can't. This section
  2966. covers advanced concepts about to constant expressions; only readers with a
  2967. good understanding of `constexpr` should attempt to read this.
  2968. @subsection tutorial-appendix-constexpr-stripping Constexpr stripping
  2969. Let's start with a challenging question. Should the following code compile?
  2970. @code{cpp}
  2971. template <typename T>
  2972. void f(T t) {
  2973. static_assert(t == 1, "");
  2974. }
  2975. constexpr int one = 1;
  2976. f(one);
  2977. @endcode
  2978. The answer is no, and the error given by Clang goes like
  2979. @code{cpp}
  2980. error: static_assert expression is not an integral constant expression
  2981. static_assert(t == 1, "");
  2982. ^~~~~~
  2983. @endcode
  2984. The explanation is that inside of `f`'s body, `t` is not a constant expression,
  2985. and hence it can't be used as the operand to a `static_assert`. The reason is
  2986. that such a function simply can't be generated by the compiler. To understand
  2987. the issue, consider what should happen when we instantiate the `f` template
  2988. with a concrete type:
  2989. @code{cpp}
  2990. // Here, the compiler should generate the code for f<int> and store the
  2991. // address of that code into fptr.
  2992. void (*fptr)(int) = f<int>;
  2993. @endcode
  2994. Clearly, the compiler can't generate `f<int>`'s code, which should trigger a
  2995. `static_assert` if `t != 1`, because we haven't specified `t` yet. Even worse,
  2996. the generated function should work on both constant and non-constant
  2997. expressions:
  2998. @code{cpp}
  2999. void (*fptr)(int) = f<int>; // assume this was possible
  3000. int i = ...; // user input
  3001. fptr(i);
  3002. @endcode
  3003. Clearly, `fptr`'s code can't be generated, because it would require being able
  3004. to `static_assert` on a runtime value, which does not make sense. Furthermore,
  3005. note that it does not matter whether you make the function `constexpr` or not;
  3006. making `f` `constexpr` would only state that the _result_ of `f` is a constant
  3007. expression whenever its argument is a constant expression, but it still does
  3008. not give you the ability to know whether you were called with a constant
  3009. expression from `f`'s body. In other words, what we would want is something
  3010. like:
  3011. @code{cpp}
  3012. template <typename T>
  3013. void f(constexpr T t) {
  3014. static_assert(t == 1, "");
  3015. }
  3016. constexpr int one = 1;
  3017. f(one);
  3018. @endcode
  3019. In this hypothetical scenario, the compiler would know that `t` is a constant
  3020. expression from the body of `f`, and the `static_assert` could be made to work.
  3021. However, `constexpr` parameters do not exist in the current language, and
  3022. adding them would bring up very challenging design and implementation issues.
  3023. The conclusion of this little experiment is that __argument passing strips
  3024. away `constexpr`-ness__. What might be unclear by now are the consequences
  3025. of this stripping, which are explained next.
  3026. @subsection tutorial-tutorial-appendix-constexpr-preservation Constexpr preservation
  3027. The fact that an argument is not a constant expression means that we can't use
  3028. it as a non-type template parameter, as an array bound, inside a `static_assert`
  3029. or anything else that requires a constant expression. In addition, this means
  3030. that the return type of a function can't depend on the _value_ of an argument
  3031. which is nothing new if you think about it:
  3032. @code{cpp}
  3033. template <int i>
  3034. struct foo { };
  3035. auto f(int i) -> foo<i>; // obviously won't work
  3036. @endcode
  3037. In fact, the return type of a function may only depend on the types of its
  3038. arguments, and `constexpr` can't change this fact. This is of utmost importance
  3039. to us, because we're interested in manipulating heterogeneous objects, which
  3040. eventually means returning objects with different types depending on the
  3041. argument of the function. For example, a function might want to return an
  3042. object of type `T` in one case and an object of type `U` in the other;
  3043. from our analysis, we now know that these "cases" will have to depend on
  3044. information encoded in the _types_ of the arguments, not in their _values_.
  3045. To preserve `constexpr`-ness through argument passing, we have to encode the
  3046. `constexpr` value into a type, and then pass a not-necessarily-`constexpr`
  3047. object of that type to the function. The function, which must be a template,
  3048. may then access the `constexpr` value encoded inside that type.
  3049. @todo
  3050. Improve this explanation and talk about non-integral constant expressions
  3051. wrapped into types.
  3052. @subsection tutorial-appendix-constexpr-effects Side effects
  3053. Let me ask a tricky question. Is the following code valid?
  3054. @code{cpp}
  3055. template <typename T>
  3056. constexpr int f(T& n) { return 1; }
  3057. int n = 0;
  3058. constexpr int i = f(n);
  3059. @endcode
  3060. The answer is _yes_, but the reason might not be obvious at first. What
  3061. happens here is that we have a non-`constexpr` `int n`, and a `constexpr`
  3062. function `f` taking a reference to its argument. The reason why most people
  3063. think it shouldn't work is that `n` is not `constexpr`. However, we're not
  3064. doing anything with `n` inside of `f`, so there is no actual reason why this
  3065. shouldn't work! This is a bit like `throw`ing inside of a `constexpr` function:
  3066. @code{cpp}
  3067. constexpr int sqrt(int i) {
  3068. if (i < 0) throw "i should be non-negative";
  3069. return ...;
  3070. }
  3071. constexpr int two = sqrt(4); // ok: did not attempt to throw
  3072. constexpr int error = sqrt(-4); // error: can't throw in a constant expression
  3073. @endcode
  3074. As long as the code path where `throw` appears is not executed, the result of
  3075. the invocation can be a constant expression. Similarly, we can do whatever we
  3076. want inside of `f`, as long as we don't execute a code path that requires
  3077. accessing its argument `n`, which is not a constant expression:
  3078. @code{cpp}
  3079. template <typename T>
  3080. constexpr int f(T& n, bool touch_n) {
  3081. if (touch_n) n + 1;
  3082. return 1;
  3083. }
  3084. int n = 0;
  3085. constexpr int i = f(n, false); // ok
  3086. constexpr int j = f(n, true); // error
  3087. @endcode
  3088. The error given by Clang for the second invocation is
  3089. @code{cpp}
  3090. error: constexpr variable 'j' must be initialized by a constant expression
  3091. constexpr int j = f(n, true); // error
  3092. ^ ~~~~~~~~~~
  3093. note: read of non-const variable 'n' is not allowed in a constant expression
  3094. if (touch_n) n + 1;
  3095. ^
  3096. @endcode
  3097. Let's now step the game up a bit and consider a more subtle example.
  3098. Is the following code valid?
  3099. @code{cpp}
  3100. template <typename T>
  3101. constexpr int f(T n) { return 1; }
  3102. int n = 0;
  3103. constexpr int i = f(n);
  3104. @endcode
  3105. The only difference with our initial scenario is that `f` now takes its
  3106. argument by value instead of by reference. However, this makes a world of
  3107. difference. Indeed, we're now asking the compiler to make a copy of `n`
  3108. and to pass this copy to `f`. However, `n` is not `constexpr`, so its
  3109. value is only known at runtime. How could the compiler make a copy (at
  3110. compile-time) of a variable whose value is only known at runtime? Of
  3111. course, it can't. Indeed, the error message given by Clang is pretty
  3112. explicit about what's happening:
  3113. @code{cpp}
  3114. error: constexpr variable 'i' must be initialized by a constant expression
  3115. constexpr int i = f(n);
  3116. ^ ~~~~
  3117. note: read of non-const variable 'n' is not allowed in a constant expression
  3118. constexpr int i = f(n);
  3119. ^
  3120. @endcode
  3121. @todo
  3122. Explain how side-effects may not appear inside constant expressions, even
  3123. if the expression they yield are not accessed.
  3124. <!-------------------
  3125. Let me ask a tricky question. Is the following code valid?
  3126. @code{cpp}
  3127. template <typename X>
  3128. auto identity(X x) { return x; }
  3129. static_assert(value(identity(bool_c<true>)), "");
  3130. @endcode
  3131. The answer is "no", but the reason might not be obvious at first. Even more
  3132. puzzling is that the following code is perfectly valid:
  3133. @snippet example/tutorial/constant_side_effects.cpp pure
  3134. To understand why the compiler can't possibly evaluate the first assertion
  3135. at compile-time, notice that `identity` was not marked `constexpr` and
  3136. consider the following alternative (but valid) definition for `identity`:
  3137. @snippet example/tutorial/constant_side_effects.cpp impure_identity
  3138. The signature of the function did not change; the function could even have
  3139. been defined in a separate source file. However, it is now obvious that the
  3140. compiler can't evaluate that expression at compile-time. On the other hand,
  3141. when we write
  3142. @snippet example/tutorial/constant_side_effects.cpp impure
  3143. we're telling the compiler to perform those potential side effects during the
  3144. dynamic initialization phase! Then, we use `value` to return the compile-time
  3145. value associated to its argument. Also note that `value` takes a `const&` to
  3146. its argument; if it tried taking it by value, we would be reading from a
  3147. non-`constexpr` variable to do the copying, and that could hide side-effects.
  3148. ------>
  3149. @section tutorial-appendix-MPL Appendix II: A minimal MPL
  3150. ------------------------------------------------------------------------------
  3151. This section presents a mini reimplementation of the MPL library. The goal is
  3152. to be as backward compatible as possible with the MPL, while still using Hana
  3153. under the hood. Only the "Algorithms" part of the MPL is implemented as a case
  3154. study, but it should be possible to implement many (but not all) metafunctions
  3155. of the MPL.
  3156. Scroll down to the `main` function to see the tests. The tests are exactly
  3157. the examples in the MPL documentation that were copy/pasted and then
  3158. modified as little as possible to work with this reimplementation.
  3159. @include example/tutorial/appendix_mpl.cpp
  3160. <!-- Links -->
  3161. [Boost.Devel]: http://lists.boost.org/Archives/boost
  3162. [Boost.Fusion]: http://www.boost.org/doc/libs/release/libs/fusion/doc/html/index.html
  3163. [Boost.MPL]: http://www.boost.org/doc/libs/release/libs/mpl/doc/index.html
  3164. [Boost.Steering]: https://sites.google.com/a/boost.org/steering/home
  3165. [Boost]: http://www.boost.org
  3166. [Brigand]: https://github.com/edouarda/brigand
  3167. [C++14.auto_rt]: http://en.wikipedia.org/wiki/C%2B%2B14#Function_return_type_deduction
  3168. [C++14.gconstexpr]: http://en.wikipedia.org/wiki/C%2B%2B11#constexpr_.E2.80.93_Generalized_constant_expressions
  3169. [C++14.glambda]: http://en.wikipedia.org/wiki/C%2B%2B14#Generic_lambdas
  3170. [C++14.ice]: http://en.cppreference.com/w/cpp/types/integral_constant
  3171. [C++14.udl]: http://en.wikipedia.org/wiki/C%2B%2B11#User-defined_literals
  3172. [C++14.vtemplate]: http://en.wikipedia.org/wiki/C%2B%2B14#Variable_templates
  3173. [C++14]: http://en.wikipedia.org/wiki/C%2B%2B14
  3174. [C++17.clite]: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3580.pdf
  3175. [C++Now]: http://cppnow.org
  3176. [Chandler.MeetingC++]: https://youtu.be/qkzaZumt_uk?t=4478
  3177. [CMake]: http://www.cmake.org
  3178. [constexpr_throw]: http://stackoverflow.com/a/8626450/627587
  3179. [CopyConstructible]: http://en.cppreference.com/w/cpp/named_req/CopyConstructible
  3180. [CppCon]: http://cppcon.org
  3181. [GOTW]: http://www.gotw.ca/gotw/index.htm
  3182. [GSoC]: http://www.google-melange.com/gsoc/homepage/google/gsoc2014
  3183. [Hana.chat]: https://gitter.im/boostorg/hana
  3184. [Hana.contributing]: https://github.com/boostorg/hana/blob/master/CONTRIBUTING.md#how-to-contribute
  3185. [Hana.hacking]: https://github.com/boostorg/hana/blob/master/README.md#hacking-on-hana
  3186. [Hana.issues]: https://github.com/boostorg/hana/issues
  3187. [Hana.repository]: https://github.com/boostorg/hana
  3188. [Hana.StackOverflow]: http://stackoverflow.com/questions/tagged/boost-hana
  3189. [Hana.wiki]: https://github.com/boostorg/hana/wiki
  3190. [Homebrew]: http://brew.sh
  3191. [ldionne.talks]: http://ldionne.com/talks
  3192. [lie-to-children]: http://en.wikipedia.org/wiki/Lie-to-children
  3193. [Meeting C++]: https://meetingcpp.com
  3194. [Metabench]: http://metaben.ch
  3195. [MPL.arithmetic]: http://www.boost.org/doc/libs/release/libs/mpl/doc/refmanual/arithmetic-operations.html
  3196. [MPL.metafunction]: http://www.boost.org/doc/libs/release/libs/mpl/doc/refmanual/metafunction.html
  3197. [MPL.mfc]: http://www.boost.org/doc/libs/release/libs/mpl/doc/refmanual/metafunction-class.html
  3198. [MPL11]: http://github.com/ldionne/mpl11
  3199. [N4461]: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4461.html
  3200. [N4487]: https://isocpp.org/files/papers/N4487.pdf
  3201. [pkg-config]: http://www.freedesktop.org/wiki/Software/pkg-config/
  3202. [POD]: http://en.cppreference.com/w/cpp/named_req/PODType
  3203. [SFINAE]: http://en.cppreference.com/w/cpp/language/sfinae
  3204. [slides.inst_must_go1]: https://github.com/boostcon/2010_presentations/raw/master/mon/instantiations_must_go.pdf
  3205. [slides.inst_must_go2]: https://github.com/boostcon/2010_presentations/raw/master/mon/instantiations_must_go_2.pdf
  3206. [SO.sfinae]: http://stackoverflow.com/a/257382/627587
  3207. [Sprout]: https://github.com/bolero-MURAKAMI/Sprout
  3208. [StackOverflow]: http://stackoverflow.com
  3209. [video.inst_must_go]: https://www.youtube.com/watch?v=x7UmrRzKAXU
  3210. */