]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | # Boost.Hana <a target="_blank" href="http://semver.org">![Version][badge.version]</a> <a target="_blank" href="https://travis-ci.org/boostorg/hana">![Travis status][badge.Travis]</a> <a target="_blank" href="https://ci.appveyor.com/project/ldionne/hana">![Appveyor status][badge.Appveyor]</a> <a target="_blank" href="http://melpon.org/wandbox/permlink/g4ozIK33ITDtyGa3">![Try it online][badge.wandbox]</a> <a target="_blank" href="https://gitter.im/boostorg/hana">![Gitter Chat][badge.Gitter]</a> |
2 | ||
3 | > Your standard library for metaprogramming | |
4 | ||
5 | ## Overview | |
6 | <!-- Important: keep this in sync with example/overview.cpp --> | |
7 | ```cpp | |
8 | #include <boost/hana.hpp> | |
9 | #include <cassert> | |
10 | #include <string> | |
11 | namespace hana = boost::hana; | |
12 | using namespace hana::literals; | |
13 | ||
14 | struct Fish { std::string name; }; | |
15 | struct Cat { std::string name; }; | |
16 | struct Dog { std::string name; }; | |
17 | ||
18 | int main() { | |
19 | // Sequences capable of holding heterogeneous objects, and algorithms | |
20 | // to manipulate them. | |
21 | auto animals = hana::make_tuple(Fish{"Nemo"}, Cat{"Garfield"}, Dog{"Snoopy"}); | |
22 | auto names = hana::transform(animals, [](auto a) { | |
23 | return a.name; | |
24 | }); | |
25 | assert(hana::reverse(names) == hana::make_tuple("Snoopy", "Garfield", "Nemo")); | |
26 | ||
27 | // No compile-time information is lost: even if `animals` can't be a | |
28 | // constant expression because it contains strings, its length is constexpr. | |
29 | static_assert(hana::length(animals) == 3u, ""); | |
30 | ||
31 | // Computations on types can be performed with the same syntax as that of | |
32 | // normal C++. Believe it or not, everything is done at compile-time. | |
33 | auto animal_types = hana::make_tuple(hana::type_c<Fish*>, hana::type_c<Cat&>, hana::type_c<Dog*>); | |
34 | auto animal_ptrs = hana::filter(animal_types, [](auto a) { | |
35 | return hana::traits::is_pointer(a); | |
36 | }); | |
37 | static_assert(animal_ptrs == hana::make_tuple(hana::type_c<Fish*>, hana::type_c<Dog*>), ""); | |
38 | ||
39 | // And many other goodies to make your life easier, including: | |
40 | // 1. Access to elements in a tuple with a sane syntax. | |
41 | static_assert(animal_ptrs[0_c] == hana::type_c<Fish*>, ""); | |
42 | static_assert(animal_ptrs[1_c] == hana::type_c<Dog*>, ""); | |
43 | ||
44 | // 2. Unroll loops at compile-time without hassle. | |
45 | std::string s; | |
46 | hana::int_c<10>.times([&]{ s += "x"; }); | |
47 | // equivalent to s += "x"; s += "x"; ... s += "x"; | |
48 | ||
49 | // 3. Easily check whether an expression is valid. | |
50 | // This is usually achieved with complex SFINAE-based tricks. | |
51 | auto has_name = hana::is_valid([](auto&& x) -> decltype((void)x.name) { }); | |
52 | static_assert(has_name(animals[0_c]), ""); | |
53 | static_assert(!has_name(1), ""); | |
54 | } | |
55 | ``` | |
56 | ||
57 | ||
58 | ## Documentation | |
59 | You can browse the documentation online at http://boostorg.github.io/hana. | |
b32b8144 FG |
60 | The documentation covers everything you should need including installing the |
61 | library, a tutorial explaining what Hana is and how to use it, and an extensive | |
62 | reference section with examples. The remainder of this README is mostly for | |
63 | people that wish to work on the library itself, not for its users. | |
64 | ||
65 | An offline copy of the documentation can be obtained by checking out the | |
66 | `gh-pages` branch. To avoid overwriting the current directory, you can clone | |
67 | the `gh-pages` branch into a subdirectory like `doc/html`: | |
7c673cae FG |
68 | ```shell |
69 | git clone http://github.com/boostorg/hana --branch=gh-pages --depth=1 doc/html | |
70 | ``` | |
71 | ||
72 | After issuing this, `doc/html` will contain exactly the same static website | |
b32b8144 | 73 | that is [available online][Hana.docs]. Note that `doc/html` is automatically |
7c673cae FG |
74 | ignored by Git so updating the documentation won't pollute your index. |
75 | ||
76 | ||
77 | ## Hacking on Hana | |
78 | Setting yourself up to work on Hana is easy. First, you will need an | |
79 | installation of [CMake][]. Once this is done, you can `cd` to the root | |
80 | of the project and setup the build directory: | |
81 | ```shell | |
82 | mkdir build | |
83 | cd build | |
84 | cmake .. | |
85 | ``` | |
86 | ||
87 | Usually, you'll want to specify a custom compiler because the system's | |
88 | compiler is too old: | |
89 | ```shell | |
90 | cmake .. -DCMAKE_CXX_COMPILER=/path/to/compiler | |
91 | ``` | |
92 | ||
93 | Usually, this will work just fine. However, on some systems, the standard | |
94 | library and/or compiler provided by default does not support C++14. If | |
95 | this is your case, the [wiki][Hana.wiki] has more information about | |
96 | setting you up on different systems. | |
97 | ||
98 | Normally, Hana tries to find Boost headers if you have them on your system. | |
99 | It's also fine if you don't have them; a few tests requiring the Boost headers | |
100 | will be disabled in that case. However, if you'd like Hana to use a custom | |
101 | installation of Boost, you can specify the path to this custom installation: | |
102 | ```shell | |
103 | cmake .. -DCMAKE_CXX_COMPILER=/path/to/compiler -DBOOST_ROOT=/path/to/boost | |
104 | ``` | |
105 | ||
106 | You can now build and run the unit tests and the examples: | |
107 | ```shell | |
108 | cmake --build . --target check | |
109 | ``` | |
110 | ||
111 | You should be aware that compiling the unit tests is pretty time and RAM | |
112 | consuming, especially the tests for external adapters. This is due to the | |
113 | fact that Hana's unit tests are very thorough, and also that heterogeneous | |
114 | sequences in other libraries tend to have horrible compile-time performance. | |
115 | ||
116 | There are also optional targets which are enabled only when the required | |
117 | software is available on your computer. For example, generating the | |
118 | documentation requires [Doxygen][] to be installed. An informative message | |
119 | will be printed during the CMake generation step whenever an optional target | |
120 | is disabled. You can install any missing software and then re-run the CMake | |
121 | generation to update the list of available targets. | |
122 | ||
123 | > #### Tip | |
124 | > You can use the `help` target to get a list of all the available targets. | |
125 | ||
126 | If you want to add unit tests or examples, just add a source file in `test/` | |
127 | or `example/` and then re-run the CMake generation step so the new source | |
128 | file is known to the build system. Let's suppose the relative path from the | |
129 | root of the project to the new source file is `path/to/file.cpp`. When you | |
130 | re-run the CMake generation step, a new target named `path.to.file` will be | |
131 | created, and a test of the same name will also be created. Hence, | |
132 | ```shell | |
133 | cd build # Go back to the build directory | |
134 | cmake --build . --target path.to.file # Builds the program associated to path/to/file.cpp | |
135 | ctest -R path.to.file # Runs the program as a test | |
136 | ``` | |
137 | ||
138 | > #### Tip for Sublime Text users | |
139 | > If you use the provided [hana.sublime-project](hana.sublime-project) file, | |
140 | > you can select the "[Hana] Build current file" build system. When viewing a | |
141 | > file to which a target is associated (like a test or an example), you can | |
142 | > then compile it by pressing ⌘B, or compile and then run it using ⇧⌘B. | |
143 | ||
144 | ||
145 | ## Project organization | |
146 | The project is organized in a couple of subdirectories. | |
147 | - The [benchmark](benchmark) directory contains compile-time and runtime | |
148 | benchmarks to make sure the library is as fast as advertised. The benchmark | |
149 | code is written mostly in the form of [eRuby][] templates. The templates | |
150 | are used to generate C++ files which are then compiled while gathering | |
151 | compilation and execution statistics. | |
152 | - The [cmake](cmake) directory contains various CMake modules and other | |
153 | scripts needed by the build system. | |
154 | - The [doc](doc) directory contains configuration files needed to generate | |
155 | the documentation. The `doc/html` subdirectory is automatically ignored | |
156 | by Git; you can conveniently store a local copy of the documentation by | |
157 | cloning the `gh-pages` branch into that directory, as explained above. | |
158 | - The [example](example) directory contains the source code for all the | |
159 | examples of both the tutorial and the reference documentation. | |
7c673cae FG |
160 | - The [include](include) directory contains the library itself, which is |
161 | header only. | |
162 | - The [test](test) directory contains the source code for all the unit tests. | |
163 | ||
164 | ||
7c673cae FG |
165 | ## Contributing |
166 | Please see [CONTRIBUTING.md](CONTRIBUTING.md). | |
167 | ||
168 | ||
169 | ## License | |
170 | Please see [LICENSE.md](LICENSE.md). | |
171 | ||
172 | ||
173 | ## Releasing | |
174 | This section acts as a reminder of the few simple steps required to release a | |
175 | new version of the library. This is only relevant to Hana's developers. To | |
b32b8144 FG |
176 | release a new version of the library, make sure the current version in |
177 | `include/boost/hana/version.hpp` matches the release you're about to publish. | |
178 | Then, create an annotated tag with: | |
179 | ```sh | |
180 | git tag -a --file=- v<version> <<EOM | |
181 | ...your message here... | |
182 | EOM | |
183 | ``` | |
184 | ||
7c673cae FG |
185 | Then, push the tag and create a new GitHub release pointing to that tag. |
186 | Once that is done, bump the version number in `include/boost/hana/version.hpp` | |
b32b8144 FG |
187 | so that it matches the next _planned_ release. Finally, do not forget to update |
188 | the [Homebrew formula][] to point to the latest version. | |
7c673cae FG |
189 | |
190 | ||
191 | <!-- Links --> | |
192 | [badge.Appveyor]: https://ci.appveyor.com/api/projects/status/github/boostorg/hana?svg=true&branch=master | |
193 | [badge.Gitter]: https://img.shields.io/badge/gitter-join%20chat-blue.svg | |
194 | [badge.Travis]: https://travis-ci.org/boostorg/hana.svg?branch=master | |
195 | [badge.version]: https://badge.fury.io/gh/boostorg%2Fhana.svg | |
196 | [badge.Wandbox]: https://img.shields.io/badge/try%20it-online-blue.svg | |
7c673cae | 197 | [CMake]: http://www.cmake.org |
7c673cae FG |
198 | [Doxygen]: http://www.doxygen.org |
199 | [eRuby]: http://en.wikipedia.org/wiki/ERuby | |
200 | [Hana.docs]: http://boostorg.github.io/hana | |
201 | [Hana.wiki]: https://github.com/boostorg/hana/wiki | |
b32b8144 | 202 | [Homebrew formula]: https://github.com/Homebrew/homebrew-core/blob/master/Formula/hana.rb |