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 #include <boost/hana.hpp>
6 
7 #include <functional>
8 #include <iostream>
9 #include <string>
10 #include <type_traits>
11 #include <utility>
12 namespace hana = boost::hana;
13 using namespace hana::literals;
14 using namespace std::literals;
15 
16 
17 //////////////////////////////////////////////////////////////////////////////
18 // Welcome to Hana!
19 //
20 // You can play around and press 'Run' at the bottom of this file to compile
21 // and run this code.
22 //
23 // To get you started, here's a small JSON generator written with Hana
24 // (this is explained in the tutorial if you're interested):
25 //////////////////////////////////////////////////////////////////////////////
26 
27 // 1. Define some utilities
28 template <typename Xs>
join(Xs && xs,std::string sep)29 std::string join(Xs&& xs, std::string sep) {
30   return hana::fold(hana::intersperse(std::forward<Xs>(xs), sep), "", std::plus<>{});
31 }
32 
quote(std::string s)33 std::string quote(std::string s) { return "\"" + s + "\""; }
34 
35 template <typename T>
to_json(T const & x)36 auto to_json(T const& x) -> decltype(std::to_string(x)) {
37   return std::to_string(x);
38 }
39 
to_json(char c)40 std::string to_json(char c) { return quote({c}); }
to_json(std::string s)41 std::string to_json(std::string s) { return quote(s); }
42 
43 
44 // 2. Define how to print user-defined types
45 template <typename T>
46   std::enable_if_t<hana::Struct<T>::value,
to_json(T const & x)47 std::string> to_json(T const& x) {
48   auto json = hana::transform(hana::keys(x), [&](auto name) {
49     auto const& member = hana::at_key(x, name);
50     return quote(hana::to<char const*>(name)) + " : " + to_json(member);
51   });
52 
53   return "{" + join(std::move(json), ", ") + "}";
54 }
55 
56 // 3. Define how to print Sequences
57 template <typename Xs>
58   std::enable_if_t<hana::Sequence<Xs>::value,
to_json(Xs const & xs)59 std::string> to_json(Xs const& xs) {
60   auto json = hana::transform(xs, [](auto const& x) {
61     return to_json(x);
62   });
63 
64   return "[" + join(std::move(json), ", ") + "]";
65 }
66 
67 
68 // 4. Create your own types and make them compatible with Hana.
69 //    This can be done intrusively or non-intrusively.
70 struct Car {
71   BOOST_HANA_DEFINE_STRUCT(Car,
72     (std::string, brand),
73     (std::string, model)
74   );
75 };
76 
main()77 int main() {
78   // 5. Generate beautiful JSON without hassle. Enjoy!
79   auto cars = hana::make_tuple(
80     Car{"BMW", "Z3"},
81     Car{"Audi", "A4"},
82     Car{"Ferrari", "F40"},
83     Car{"Lamborghini", "Diablo"}
84     // ...
85   );
86 
87   std::cout << to_json(cars) << std::endl;
88 }
89