Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:37:57

0001 /*
0002 @file
0003 Defines `boost::hana::experimental::print`.
0004 
0005 Copyright Louis Dionne 2013-2022
0006 Distributed under the Boost Software License, Version 1.0.
0007 (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
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 // models for different containers
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     //! @cond
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     //! @endcond
0057 
0058     //! @ingroup group-experimental
0059     //! Returns a string representation of the given object.
0060     //!
0061     //! This function is defined for most containers provided by Hana, and
0062     //! also for objects that define an `operator<<` that can be used with
0063     //! a `std::basic_ostream`. It can recursively print containers within
0064     //! containers, but do not expect any kind of proper indentation.
0065     //!
0066     //! This function requires (the rest of) Boost to be available on the
0067     //! system. It also requires RTTI to be enabled.
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     // Define the `Printable` concept
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     // model for Sequences
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     // model for OutputStreamable types
0122     //! @cond
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     //! @endcond
0135 
0136     // model for hana::optional
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     // model for hana::maps
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     // model for hana::metafunctions
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     // model for hana::metafunction_classes
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     // model for Constants holding a `Printable`
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     // model for Products
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     // model for hana::strings
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     // model for hana::sets
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     // model for hana::templates
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     // model for hana::types
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 } }} // end namespace boost::hana
0256 
0257 #endif // !BOOST_HANA_EXPERIMENTAL_PRINTABLE_HPP