mimic++ v9.2.1
Loading...
Searching...
No Matches
Templated.hpp
Go to the documentation of this file.
1// Copyright Dominic (DNKpp) Koepke 2024 - 2025.
2// Distributed under the Boost Software License, Version 1.0.
3// (See accompanying file LICENSE_1_0.txt or copy at
4// https://www.boost.org/LICENSE_1_0.txt)
5
6#ifndef MIMICPP_PRINTING_TYPE_TEMPLATED_HPP
7#define MIMICPP_PRINTING_TYPE_TEMPLATED_HPP
8
9#pragma once
10
11#include "mimic++/Fwd.hpp"
17
18#ifndef MIMICPP_DETAIL_IS_MODULE
19 #include <algorithm>
20 #include <concepts>
21 #include <functional>
22 #include <memory>
23 #include <memory_resource>
24 #include <type_traits>
25 #include <utility>
26#endif
27
28namespace mimicpp::printing::type::detail
29{
30#ifdef MIMICPP_CONFIG_EXPERIMENTAL_PRETTY_TYPES
31
32 template <typename T, print_iterator OutIter>
33 constexpr OutIter pretty_template_name(OutIter out)
34 {
35 StringT name = type_name<T>();
36 auto const iter = std::ranges::find(name, '<');
37 MIMICPP_ASSERT(iter != name.cend(), "Given name is not a template.");
38 name.erase(iter, name.end());
39
40 return type::prettify_type(std::move(out), std::move(name));
41 }
42
43 template <typename NameGenerator>
44 struct basic_template_type_printer
45 {
46 template <print_iterator OutIter>
47 static constexpr OutIter print(OutIter out)
48 {
49 return std::invoke(NameGenerator{}, std::move(out));
50 }
51 };
52
53 template <typename Type, template <typename...> typename Template, typename LeadingArgList>
54 struct is_default_arg_for
55 : public std::false_type
56 {
57 };
58
59 template <typename Type, template <typename...> typename Template, typename... LeadingArgs>
60 requires requires { typename Template<LeadingArgs...>; }
61 struct is_default_arg_for<Type, Template, util::type_list<LeadingArgs...>>
62 : public std::is_same<
63 Template<LeadingArgs...>,
64 Template<LeadingArgs..., Type>>
65 {
66 };
67
68 template <typename Type, template <typename...> typename Template, typename LeadingArgList>
69 concept default_arg_for = is_default_arg_for<Type, Template, LeadingArgList>::value;
70
71 template <typename List>
72 struct type_list_pop_back_if_can
73 : public util::type_list_pop_back<List>
74 {
75 };
76
77 template <>
78 struct type_list_pop_back_if_can<util::type_list<>>
79 {
80 using type = util::type_list<>;
81 };
82
83 template <
84 typename ArgList,
85 template <typename...> typename Template,
86 typename PopBack = type_list_pop_back_if_can<ArgList>>
87 struct drop_default_args_for_impl
88 {
89 using type = ArgList;
90 };
91
92 template <typename ArgList, template <typename...> typename Template, typename PopBack>
93 requires requires { typename PopBack::popped; }
94 && default_arg_for<typename PopBack::popped, Template, typename PopBack::type>
95 struct drop_default_args_for_impl<ArgList, Template, PopBack>
96 : public drop_default_args_for_impl<typename PopBack::type, Template>
97 {
98 };
99
100 template <template <typename...> typename Template, typename ArgList>
101 struct drop_default_args_for
102 : public drop_default_args_for_impl<ArgList, Template>
103 {
104 };
105
106 template <template <typename...> typename Template, typename ArgList>
107 struct template_type_name_generator_fn
108 {
109 template <print_iterator OutIter>
110 constexpr OutIter operator()(OutIter out) const
111 {
112 using MinimalArgList = typename drop_default_args_for<Template, ArgList>::type;
113 using Type = util::type_list_populate_t<Template, MinimalArgList>;
114
115 out = pretty_template_name<Type>(std::move(out));
116 out = format::format_to(std::move(out), "<");
117 out = print_separated(std::move(out), ", ", MinimalArgList{});
118 out = format::format_to(std::move(out), ">");
119
120 return out;
121 }
122 };
123
124 template <template <typename...> typename Template, typename... Ts>
125 struct template_type_printer<Template<Ts...>>
126 : public basic_template_type_printer<
127 template_type_name_generator_fn<Template, util::type_list<Ts...>>>
128 {
129 };
130
131 template <typename Allocator>
132 struct is_pmr_allocator
133 : public std::false_type
134 {
135 };
136
137 template <typename T>
138 struct is_pmr_allocator<std::pmr::polymorphic_allocator<T>>
139 : public std::true_type
140 {
141 };
142
143 template <template <typename...> typename Template, typename... Ts>
144 concept std_pmr_container =
145 requires {
146 typename Template<Ts...>::allocator_type;
147 typename Template<Ts...>::value_type;
148 }
149 && is_pmr_allocator<typename Template<Ts...>::allocator_type>::value
150 && default_arg_for<std::allocator<typename Template<Ts...>::value_type>, Template, util::type_list_pop_back_t<util::type_list<Ts...>>>;
151
152 static constexpr StringViewT stdPrefix{"std::"};
153
154 template <template <typename...> typename Template, typename ArgList>
155 struct potential_pmr_container_type_name_generator_fn
156 {
157 template <print_iterator OutIter>
158 OutIter operator()(OutIter out) const
159 {
160 StringT const name = std::invoke(
161 [] {
162 StringStreamT stream{};
163 std::invoke(
164 template_type_name_generator_fn<
165 Template,
166 util::type_list_pop_back_t<ArgList>>{},
167 std::ostreambuf_iterator{stream});
168 return std::move(stream).str();
169 });
170
171 // we do not want to accidentally manipulate non-std types, so make sure the `std::`` is actually part of the type
172 if (name.starts_with(stdPrefix))
173 {
174 out = format::format_to(std::move(out), "std::pmr::");
175 out = std::ranges::copy(
176 name.cbegin() + stdPrefix.size(),
177 name.cend(),
178 std::move(out))
179 .out;
180 }
181 // It's not an actual `std` type, but we've removed the allocator for the name generation, thus we need
182 // generate it again with the actual allocator.
183 else
184 {
185 out = std::invoke(
186 template_type_name_generator_fn<Template, ArgList>{},
187 std::move(out));
188 }
189
190 return out;
191 }
192 };
193
194 template <template <typename...> typename Template, typename... Ts>
195 requires std_pmr_container<Template, Ts...>
196 struct template_type_printer<Template<Ts...>>
197 : public basic_template_type_printer<
198 potential_pmr_container_type_name_generator_fn<Template, util::type_list<Ts...>>>
199 {
200 };
201
202 template <template <typename, auto...> typename Template, typename T, auto n>
203 struct array_like_name_generator
204 {
205 template <print_iterator OutIter>
206 constexpr OutIter operator()(OutIter out) const
207 {
208 out = pretty_template_name<Template<T, n>>(std::move(out));
209 out = format::format_to(std::move(out), "<");
210 out = mimicpp::print_type<T>(std::move(out));
211
212 if constexpr (constexpr bool isDefaultSize = requires { requires std::same_as<Template<T>, Template<T, n>>; };
213 !isDefaultSize)
214 {
215 out = format::format_to(std::move(out), ", {}", n);
216 }
217
218 out = format::format_to(std::move(out), ">");
219
220 return out;
221 }
222 };
223
224 // used for array, span and the like
225 // should also handle c++26s inplace_vector
226 // see: https://en.cppreference.com/w/cpp/container/inplace_vector
227 template <template <typename, auto...> typename Template, typename T, auto n>
228 struct template_type_printer<Template<T, n>>
229 : public basic_template_type_printer<
230 array_like_name_generator<Template, T, n>>
231 {
232 };
233
234#endif
235
236}
237
238#endif
#define MIMICPP_ASSERT(condition, msg)
Definition Config.hpp:51
constexpr TypeMatcher< T > type
Matcher, which can be used as a last resort to disambiguate similar overloads.
Definition GeneralMatchers.hpp:297
constexpr printing::PrintFn print
Functional object, converting the given object to its textual representation.
Definition Print.hpp:183
StringT type_name()
Returns the (potentially demangled) name.
Definition PrintType.hpp:201
MIMICPP_DETAIL_CONSTEXPR_STRING OutIter prettify_type(OutIter out, StringT name)
Prettifies a demangled name.
Definition PrintType.hpp:207
constexpr printing::PrintTypeFn< T > print_type
Functional object, converting the given type to its textual representation.
Definition PrintType.hpp:478
typename type_list_pop_back< TypeList >::type type_list_pop_back_t
Definition TypeList.hpp:86
std::basic_ostringstream< CharT, CharTraitsT > StringStreamT
Definition Format.hpp:35
std::basic_string_view< CharT, CharTraitsT > StringViewT
Definition Fwd.hpp:392
std::basic_string< CharT, CharTraitsT > StringT
Definition Fwd.hpp:391