]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/hana/experimental/printable.hpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / boost / hana / experimental / printable.hpp
1 /*
2 @file
3 Defines `boost::hana::experimental::print`.
4
5 @copyright Louis Dionne 2013-2017
6 Distributed under the Boost Software License, Version 1.0.
7 (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
8 */
9
10 #ifndef BOOST_HANA_EXPERIMENTAL_PRINTABLE_HPP
11 #define BOOST_HANA_EXPERIMENTAL_PRINTABLE_HPP
12
13 #include <boost/hana/concept/constant.hpp>
14 #include <boost/hana/concept/product.hpp>
15 #include <boost/hana/concept/sequence.hpp>
16 #include <boost/hana/config.hpp>
17 #include <boost/hana/core/to.hpp>
18 #include <boost/hana/core/dispatch.hpp>
19 #include <boost/hana/first.hpp>
20 #include <boost/hana/for_each.hpp>
21 #include <boost/hana/intersperse.hpp>
22 #include <boost/hana/second.hpp>
23 #include <boost/hana/transform.hpp>
24 #include <boost/hana/tuple.hpp>
25
26 // models for different containers
27 #include <boost/hana/fwd/map.hpp>
28 #include <boost/hana/fwd/optional.hpp>
29 #include <boost/hana/fwd/set.hpp>
30 #include <boost/hana/fwd/string.hpp>
31 #include <boost/hana/fwd/type.hpp>
32
33 #include <boost/core/demangle.hpp>
34
35 #include <iostream>
36 #include <regex>
37 #include <sstream>
38 #include <string>
39 #include <typeinfo>
40 #include <utility>
41
42
43 BOOST_HANA_NAMESPACE_BEGIN namespace experimental {
44 template <typename T>
45 struct Printable;
46
47 //! @cond
48 template <typename T, typename = void>
49 struct print_impl : print_impl<T, hana::when<true>> { };
50
51 template <typename T, bool condition>
52 struct print_impl<T, hana::when<condition>> : hana::default_ {
53 template <typename ...Args>
54 static constexpr auto apply(Args&& ...) = delete;
55 };
56 //! @endcond
57
58 //! @ingroup group-experimental
59 //! Returns a string representation of the given object.
60 //!
61 //! This function is defined for most containers provided by Hana, and
62 //! also for objects that define an `operator<<` that can be used with
63 //! a `std::basic_ostream`. It can recursively print containers within
64 //! containers, but do not expect any kind of proper indentation.
65 //!
66 //! This function requires (the rest of) Boost to be available on the
67 //! system. It also requires RTTI to be enabled.
68 #ifdef BOOST_HANA_DOXYGEN_INVOKED
69 auto print = [](auto const& x) -> std::string {
70 return tag-dispatched;
71 };
72 #else
73 struct print_t {
74 template <typename T>
75 std::string operator()(T const& t) const {
76 using Tag = typename hana::tag_of<T>::type;
77 using Print = BOOST_HANA_DISPATCH_IF(print_impl<Tag>,
78 hana::experimental::Printable<Tag>::value
79 );
80
81 #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
82 static_assert(hana::experimental::Printable<Tag>::value,
83 "hana::experimental::print(t) requires 't' to be Printable");
84 #endif
85
86 return Print::apply(t);
87 }
88 };
89
90 constexpr print_t print{};
91 #endif
92
93 // Define the `Printable` concept
94 template <typename T>
95 struct Printable {
96 using Tag = typename hana::tag_of<T>::type;
97 static constexpr bool value = !hana::is_default<print_impl<Tag>>::value;
98 };
99
100 namespace print_detail {
101 std::string strip_type_junk(std::string const& str) {
102 return std::regex_replace(str, std::regex("^([a-z_]+::)*([a-z_]*)_t<"), "$2<");
103 }
104 }
105
106 // model for Sequences
107 template <typename S>
108 struct print_impl<S, hana::when<hana::Sequence<S>::value>> {
109 template <typename Xs>
110 static std::string apply(Xs const& xs) {
111 std::string result = "(";
112 auto comma_separated = hana::intersperse(xs, ", ");
113 hana::for_each(comma_separated, [&result](auto const& x) {
114 result += hana::experimental::print(x);
115 });
116 result += ")";
117 return result;
118 }
119 };
120
121 // model for OutputStreamable types
122 //! @cond
123 template <typename S>
124 struct print_impl<S, hana::when_valid<decltype(
125 std::declval<std::ostringstream&>() << std::declval<S const&>()
126 )>> {
127 template <typename T>
128 static std::string apply(T const& t) {
129 std::ostringstream os;
130 os << t;
131 return os.str();
132 }
133 };
134 //! @endcond
135
136 // model for hana::optional
137 template <>
138 struct print_impl<hana::optional_tag> {
139 template <typename O>
140 static std::string apply(O const& optional) {
141 return hana::maybe("nothing",
142 [](auto const& x) {
143 return "just(" + hana::experimental::print(x) + ")";
144 }, optional);
145 }
146 };
147
148 // model for hana::maps
149 template <>
150 struct print_impl<hana::map_tag> {
151 template <typename M>
152 static std::string apply(M const& map) {
153 std::string result = "{";
154 auto pairs = hana::transform(hana::to_tuple(map),
155 [](auto const& pair) {
156 return hana::experimental::print(hana::first(pair))
157 + " => "
158 + hana::experimental::print(hana::second(pair));
159 });
160 auto comma_separated = hana::intersperse(pairs, ", ");
161 hana::for_each(comma_separated, [&result](auto const& element) {
162 result += element;
163 });
164 result += "}";
165 return result;
166 }
167 };
168
169 // model for hana::metafunctions
170 template <template <typename ...> class F>
171 struct print_impl<hana::metafunction_t<F>> {
172 template <typename T>
173 static std::string apply(T const&) {
174 return print_detail::strip_type_junk(boost::core::demangle(typeid(T).name()));
175 }
176 };
177
178 // model for hana::metafunction_classes
179 template <typename F>
180 struct print_impl<hana::metafunction_class_t<F>> {
181 template <typename T>
182 static std::string apply(T const&) {
183 return print_detail::strip_type_junk(boost::core::demangle(typeid(T).name()));
184 }
185 };
186
187 // model for Constants holding a `Printable`
188 template <typename C>
189 struct print_impl<C, hana::when<
190 hana::Constant<C>::value &&
191 Printable<typename C::value_type>::value
192 >> {
193 template <typename T>
194 static std::string apply(T const&) {
195 constexpr auto value = hana::value<T>();
196 return hana::experimental::print(value);
197 }
198 };
199
200 // model for Products
201 template <typename P>
202 struct print_impl<P, hana::when<hana::Product<P>::value>> {
203 template <typename T>
204 static std::string apply(T const& t) {
205 return '(' + hana::experimental::print(hana::first(t))
206 + ", "
207 + hana::experimental::print(hana::second(t)) + ')';
208 }
209 };
210
211 // model for hana::strings
212 template <>
213 struct print_impl<hana::string_tag> {
214 template <typename S>
215 static std::string apply(S const& s) {
216 return '"' + std::string{hana::to<char const*>(s)} + '"';
217 }
218 };
219
220 // model for hana::sets
221 template <>
222 struct print_impl<hana::set_tag> {
223 template <typename S>
224 static std::string apply(S const& set) {
225 std::string result = "{";
226 auto as_tuple = hana::transform(hana::to_tuple(set),
227 hana::experimental::print);
228 auto comma_separated = hana::intersperse(as_tuple, ", ");
229 hana::for_each(comma_separated, [&result](auto const& element) {
230 result += element;
231 });
232 result += "}";
233 return result;
234 }
235 };
236
237 // model for hana::templates
238 template <template <typename ...> class F>
239 struct print_impl<template_t<F>> {
240 template <typename T>
241 static std::string apply(T const&) {
242 return print_detail::strip_type_junk(boost::core::demangle(typeid(T).name()));
243 }
244 };
245
246 // model for hana::types
247 template <>
248 struct print_impl<hana::type_tag> {
249 template <typename T>
250 static std::string apply(T const&) {
251 using Type = typename T::type;
252 return "type<" + boost::core::demangle(typeid(Type).name()) + '>';
253 }
254 };
255 } BOOST_HANA_NAMESPACE_END
256
257 #endif // !BOOST_HANA_EXPERIMENTAL_PRINTABLE_HPP