| 1 | // Copyright Louis Dionne 2013-2022 |
| 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 | // Make sure assert always triggers an assertion |
| 6 | #ifdef NDEBUG |
| 7 | # undef NDEBUG |
| 8 | #endif |
| 9 | |
| 10 | ////////////////////////////////////////////////////////////////////////////// |
| 11 | // Important: Keep this file in sync with the Overview in the README |
| 12 | ////////////////////////////////////////////////////////////////////////////// |
| 13 | #include <boost/hana.hpp> |
| 14 | #include <cassert> |
| 15 | #include <string> |
| 16 | namespace hana = boost::hana; |
| 17 | using namespace hana::literals; |
| 18 | |
| 19 | struct Fish { std::string name; }; |
| 20 | struct Cat { std::string name; }; |
| 21 | struct Dog { std::string name; }; |
| 22 | |
| 23 | int main() { |
| 24 | // Sequences capable of holding heterogeneous objects, and algorithms |
| 25 | // to manipulate them. |
| 26 | auto animals = hana::make_tuple(Fish{.name: "Nemo" }, Cat{.name: "Garfield" }, Dog{.name: "Snoopy" }); |
| 27 | auto names = hana::transform(animals, [](auto a) { |
| 28 | return a.name; |
| 29 | }); |
| 30 | assert(hana::reverse(names) == hana::make_tuple("Snoopy" , "Garfield" , "Nemo" )); |
| 31 | |
| 32 | // No compile-time information is lost: even if `animals` can't be a |
| 33 | // constant expression because it contains strings, its length is constexpr. |
| 34 | static_assert(hana::length(animals) == 3u, "" ); |
| 35 | |
| 36 | // Computations on types can be performed with the same syntax as that of |
| 37 | // normal C++. Believe it or not, everything is done at compile-time. |
| 38 | auto animal_types = hana::make_tuple(hana::type_c<Fish*>, hana::type_c<Cat&>, hana::type_c<Dog*>); |
| 39 | auto animal_ptrs = hana::filter(animal_types, [](auto a) { |
| 40 | return hana::traits::is_pointer(a); |
| 41 | }); |
| 42 | static_assert(animal_ptrs == hana::make_tuple(hana::type_c<Fish*>, hana::type_c<Dog*>), "" ); |
| 43 | |
| 44 | // And many other goodies to make your life easier, including: |
| 45 | // 1. Access to elements in a tuple with a sane syntax. |
| 46 | static_assert(animal_ptrs[0_c] == hana::type_c<Fish*>, "" ); |
| 47 | static_assert(animal_ptrs[1_c] == hana::type_c<Dog*>, "" ); |
| 48 | |
| 49 | // 2. Unroll loops at compile-time without hassle. |
| 50 | std::string s; |
| 51 | hana::int_c<10>.times([&]{ s += "x" ; }); |
| 52 | // equivalent to s += "x"; s += "x"; ... s += "x"; |
| 53 | |
| 54 | // 3. Easily check whether an expression is valid. |
| 55 | // This is usually achieved with complex SFINAE-based tricks. |
| 56 | auto has_name = hana::is_valid([](auto&& x) -> decltype((void)x.name) { }); |
| 57 | static_assert(has_name(animals[0_c]), "" ); |
| 58 | static_assert(!has_name(1), "" ); |
| 59 | } |
| 60 | |