File indexing completed on 2025-01-18 09:37:57
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef BOOST_HANA_EXPERIMENTAL_PRINTABLE_HPP
0011 #define BOOST_HANA_EXPERIMENTAL_PRINTABLE_HPP
0012
0013 #include <boost/hana/concept/constant.hpp>
0014 #include <boost/hana/concept/product.hpp>
0015 #include <boost/hana/concept/sequence.hpp>
0016 #include <boost/hana/config.hpp>
0017 #include <boost/hana/core/to.hpp>
0018 #include <boost/hana/core/dispatch.hpp>
0019 #include <boost/hana/first.hpp>
0020 #include <boost/hana/for_each.hpp>
0021 #include <boost/hana/intersperse.hpp>
0022 #include <boost/hana/second.hpp>
0023 #include <boost/hana/transform.hpp>
0024 #include <boost/hana/tuple.hpp>
0025
0026
0027 #include <boost/hana/fwd/map.hpp>
0028 #include <boost/hana/fwd/optional.hpp>
0029 #include <boost/hana/fwd/set.hpp>
0030 #include <boost/hana/fwd/string.hpp>
0031 #include <boost/hana/fwd/type.hpp>
0032
0033 #include <boost/core/demangle.hpp>
0034
0035 #include <iostream>
0036 #include <regex>
0037 #include <sstream>
0038 #include <string>
0039 #include <typeinfo>
0040 #include <utility>
0041
0042
0043 namespace boost { namespace hana { namespace experimental {
0044 template <typename T>
0045 struct Printable;
0046
0047
0048 template <typename T, typename = void>
0049 struct print_impl : print_impl<T, hana::when<true>> { };
0050
0051 template <typename T, bool condition>
0052 struct print_impl<T, hana::when<condition>> : hana::default_ {
0053 template <typename ...Args>
0054 static constexpr auto apply(Args&& ...) = delete;
0055 };
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068 #ifdef BOOST_HANA_DOXYGEN_INVOKED
0069 auto print = [](auto const& x) -> std::string {
0070 return tag-dispatched;
0071 };
0072 #else
0073 struct print_t {
0074 template <typename T>
0075 std::string operator()(T const& t) const {
0076 using Tag = typename hana::tag_of<T>::type;
0077 using Print = BOOST_HANA_DISPATCH_IF(print_impl<Tag>,
0078 hana::experimental::Printable<Tag>::value
0079 );
0080
0081 #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
0082 static_assert(hana::experimental::Printable<Tag>::value,
0083 "hana::experimental::print(t) requires 't' to be Printable");
0084 #endif
0085
0086 return Print::apply(t);
0087 }
0088 };
0089
0090 BOOST_HANA_INLINE_VARIABLE constexpr print_t print{};
0091 #endif
0092
0093
0094 template <typename T>
0095 struct Printable {
0096 using Tag = typename hana::tag_of<T>::type;
0097 static constexpr bool value = !hana::is_default<print_impl<Tag>>::value;
0098 };
0099
0100 namespace print_detail {
0101 inline std::string strip_type_junk(std::string const& str) {
0102 return std::regex_replace(str, std::regex("(?:struct )?([a-z_]+::)*([a-z_]*)_t<((?:struct )?[a-z:<>_]*)>"), "$2<$3>");
0103 }
0104 }
0105
0106
0107 template <typename S>
0108 struct print_impl<S, hana::when<hana::Sequence<S>::value>> {
0109 template <typename Xs>
0110 static std::string apply(Xs const& xs) {
0111 std::string result = "(";
0112 auto comma_separated = hana::intersperse(xs, ", ");
0113 hana::for_each(comma_separated, [&result](auto const& x) {
0114 result += hana::experimental::print(x);
0115 });
0116 result += ")";
0117 return result;
0118 }
0119 };
0120
0121
0122
0123 template <typename S>
0124 struct print_impl<S, hana::when_valid<decltype(
0125 std::declval<std::ostringstream&>() << std::declval<S const&>()
0126 )>> {
0127 template <typename T>
0128 static std::string apply(T const& t) {
0129 std::ostringstream os;
0130 os << t;
0131 return os.str();
0132 }
0133 };
0134
0135
0136
0137 template <>
0138 struct print_impl<hana::optional_tag> {
0139 template <typename O>
0140 static std::string apply(O const& optional) {
0141 return hana::maybe("nothing",
0142 [](auto const& x) {
0143 return "just(" + hana::experimental::print(x) + ")";
0144 }, optional);
0145 }
0146 };
0147
0148
0149 template <>
0150 struct print_impl<hana::map_tag> {
0151 template <typename M>
0152 static std::string apply(M const& map) {
0153 std::string result = "{";
0154 auto pairs = hana::transform(hana::to_tuple(map),
0155 [](auto const& pair) {
0156 return hana::experimental::print(hana::first(pair))
0157 + " => "
0158 + hana::experimental::print(hana::second(pair));
0159 });
0160 auto comma_separated = hana::intersperse(pairs, ", ");
0161 hana::for_each(comma_separated, [&result](auto const& element) {
0162 result += element;
0163 });
0164 result += "}";
0165 return result;
0166 }
0167 };
0168
0169
0170 template <template <typename ...> class F>
0171 struct print_impl<hana::metafunction_t<F>> {
0172 template <typename T>
0173 static std::string apply(T const&) {
0174 return print_detail::strip_type_junk(boost::core::demangle(typeid(T).name()));
0175 }
0176 };
0177
0178
0179 template <typename F>
0180 struct print_impl<hana::metafunction_class_t<F>> {
0181 template <typename T>
0182 static std::string apply(T const&) {
0183 return print_detail::strip_type_junk(boost::core::demangle(typeid(T).name()));
0184 }
0185 };
0186
0187
0188 template <typename C>
0189 struct print_impl<C, hana::when<
0190 hana::Constant<C>::value &&
0191 Printable<typename C::value_type>::value
0192 >> {
0193 template <typename T>
0194 static std::string apply(T const&) {
0195 constexpr auto value = hana::value<T>();
0196 return hana::experimental::print(value);
0197 }
0198 };
0199
0200
0201 template <typename P>
0202 struct print_impl<P, hana::when<hana::Product<P>::value>> {
0203 template <typename T>
0204 static std::string apply(T const& t) {
0205 return '(' + hana::experimental::print(hana::first(t))
0206 + ", "
0207 + hana::experimental::print(hana::second(t)) + ')';
0208 }
0209 };
0210
0211
0212 template <>
0213 struct print_impl<hana::string_tag> {
0214 template <typename S>
0215 static std::string apply(S const& s) {
0216 return '"' + std::string{hana::to<char const*>(s)} + '"';
0217 }
0218 };
0219
0220
0221 template <>
0222 struct print_impl<hana::set_tag> {
0223 template <typename S>
0224 static std::string apply(S const& set) {
0225 std::string result = "{";
0226 auto as_tuple = hana::transform(hana::to_tuple(set),
0227 hana::experimental::print);
0228 auto comma_separated = hana::intersperse(as_tuple, ", ");
0229 hana::for_each(comma_separated, [&result](auto const& element) {
0230 result += element;
0231 });
0232 result += "}";
0233 return result;
0234 }
0235 };
0236
0237
0238 template <template <typename ...> class F>
0239 struct print_impl<template_t<F>> {
0240 template <typename T>
0241 static std::string apply(T const&) {
0242 return print_detail::strip_type_junk(boost::core::demangle(typeid(T).name()));
0243 }
0244 };
0245
0246
0247 template <>
0248 struct print_impl<hana::type_tag> {
0249 template <typename T>
0250 static std::string apply(T const&) {
0251 using Type = typename T::type;
0252 return "type<" + boost::core::demangle(typeid(Type).name()) + '>';
0253 }
0254 };
0255 } }}
0256
0257 #endif