ALib C++ Framework
by
Library Version: 2605 R0
Documentation generated by doxygen
Loading...
Searching...
No Matches
stdformatter.hpp
Go to the documentation of this file.
1//==================================================================================================
2/// \file
3/// This header-file is part of the \aliblong.
4///
5/// Copyright 2013-2026 A-Worx GmbH, Germany.
6/// Published under #"mainpage_license".
7//==================================================================================================
8
9
10//##################################################################################################
11//################################ std::formatter<alib::strings::xyz> ##############################
12//##################################################################################################
13
14#if DOXYGEN
16#else
17# if __has_include(<format>)
18namespace std {
19# else
20namespace fmt {
21# endif
22#endif
23
24/// Standard formatter specialization for #"TString" for use with \c std::format.
25///
26/// By deriving from <c>std::formatter<std::basic_string_view<TChar>, TChar></c>,
27/// we leverage the library’s optimized handling for string views, thereby avoiding issues
28/// with non-constexpr functions in the custom formatter path.
29/// @see Chapter #"alib_strings_stdformat" of the Programmer's Manual of the module
30// \alib_strings_nl.
31/// @tparam TChar The character type.
32template<typename TChar>
33struct formatter<alib::strings::TString<TChar>, TChar>
34 : formatter<std::basic_string_view<TChar>, TChar> {
35
36 // No need to override parse() since the base class does the work
37
38 /// This function converts the given \p{str} <c>std::basic_string_view<TChar></c> and
39 /// then calls the base class's formatter, which is fully constexpr-capable.
40 /// @tparam TContext The type of the format context.
41 /// @param str The \alib string to format.
42 /// @param ctx The formatting context provided by \c std::format.
43 /// @return An iterator to the end of the output range.
44 template<typename TContext>
45 auto format(const alib::strings::TString<TChar>& str, TContext& ctx) const {
46 // Delegate formatting to the std::basic_string_view<TChar> formatter
47 return formatter<std::basic_string_view<TChar>, TChar>::format(
48 static_cast<std::basic_string_view<TChar>>(str), ctx);
49 }
50};
51
52/// Standard formatter specialization for #"TCString" for use with \c std::format.
53///
54/// By deriving from <c>std::formatter<std::basic_string_view<TChar>, TChar></c>,
55/// we leverage the library’s optimized handling for string views, thereby avoiding issues
56/// with non-constexpr functions in the custom formatter path.
57/// @see Chapter #"alib_strings_stdformat" of the Programmer's Manual of the module
58// \alib_strings_nl.
59/// @tparam TChar The character type.
60template<typename TChar>
61struct formatter<alib::strings::TCString<TChar>, TChar>
62 : formatter<std::basic_string_view<TChar>, TChar> {
63
64 // No need to override parse() since the base class does the work
65
66 /// This function converts the given \p{str} <c>std::basic_string_view<TChar></c> and
67 /// then calls the base class's formatter, which is fully constexpr-capable.
68 /// @tparam TContext The type of the format context.
69 /// @param str The \alib string to format.
70 /// @param ctx The formatting context provided by \c std::format.
71 /// @return An iterator to the end of the output range.
72 template<typename TContext>
73 auto format(const alib::strings::TCString<TChar>& str, TContext& ctx) const {
74 // Delegate formatting to the std::basic_string_view<TChar> formatter
75 return formatter<std::basic_string_view<TChar>, TChar>::format(
76 static_cast<std::basic_string_view<TChar>>(str), ctx);
77 }
78};
79
80/// Standard formatter specialization for #"TAString" for use with \c std::format.
81///
82/// By deriving from <c>std::formatter<std::basic_string_view<TChar>, TChar></c>,
83/// we leverage the library’s optimized handling for string views, thereby avoiding issues
84/// with non-constexpr functions in the custom formatter path.
85/// @see Chapter #"alib_strings_stdformat" of the Programmer's Manual of the module
86// \alib_strings_nl.
87/// @tparam TChar The character type.
88template<typename TChar, typename TAllocator>
89struct formatter<alib::strings::TAString<TChar, TAllocator>, TChar>
90 : formatter<std::basic_string_view<TChar>, TChar> {
91
92 /// This function converts the given \p{str} <c>std::basic_string_view<TChar></c> and
93 /// then calls the base class's formatter, which is fully constexpr-capable.
94 /// @tparam TContext The type of the format context.
95 /// @param str The \alib string to format.
96 /// @param ctx The formatting context provided by \c std::format.
97 /// @return An iterator to the end of the output range.
98 template<typename TContext>
99 auto format(const alib::strings::TAString<TChar, TAllocator>& str, TContext& ctx) const {
100 return formatter<std::basic_string_view<TChar>, TChar>::format(
101 static_cast<std::basic_string_view<TChar>>(str), ctx);
102 }
103};
104
105/// Standard formatter specialization for #"TSubstring" for use with \c std::format.
106///
107/// By deriving from <c>std::formatter<std::basic_string_view<TChar>, TChar></c>,
108/// we leverage the library’s optimized handling for string views, thereby avoiding issues
109/// with non-constexpr functions in the custom formatter path.
110/// @see Chapter #"alib_strings_stdformat" of the Programmer's Manual of the module
111// \alib_strings_nl.
112/// @tparam TChar The character type.
113template<typename TChar>
114struct formatter<alib::strings::TSubstring<TChar>, TChar>
115 : formatter<std::basic_string_view<TChar>, TChar> {
116
117 // No need to override parse() since the base class does the work
118
119 /// This function converts the given \p{str} <c>std::basic_string_view<TChar></c> and
120 /// then calls the base class's formatter, which is fully constexpr-capable.
121 /// @tparam TContext The type of the format context.
122 /// @param str The \alib string to format.
123 /// @param ctx The formatting context provided by \c std::format.
124 /// @return An iterator to the end of the output range.
125 template<typename TContext>
126 auto format(const alib::strings::TSubstring<TChar>& str, TContext& ctx) const {
127 // Delegate formatting to the std::basic_string_view<TChar> formatter
128 return formatter<std::basic_string_view<TChar>, TChar>::format(
129 static_cast<std::basic_string_view<TChar>>(str), ctx);
130 }
131};
132
133/// Standard formatter specialization for #"TLocalString" for use with \c std::format.
134///
135/// By deriving from <c>std::formatter<std::basic_string_view<TChar>, TChar></c>,
136/// we leverage the library’s optimized handling for string views, thereby avoiding issues
137/// with non-constexpr functions in the custom formatter path.
138/// @see Chapter #"alib_strings_stdformat" of the Programmer's Manual of the module
139// \alib_strings_nl.
140/// @tparam TChar The character type.
141template<typename TChar, alib::integer TCapacity, typename TAllocator>
142struct formatter<alib::strings::TLocalString<TChar,TCapacity,TAllocator>, TChar>
143 : formatter<std::basic_string_view<TChar>, TChar> {
144// No need to override parse() since the base class does the work
145
146 /// This function converts the given \p{str} <c>std::basic_string_view<TChar></c> and
147 /// then calls the base class's formatter, which is fully constexpr-capable.
148 /// @tparam TContext The type of the format context.
149 /// @param str The \alib string to format.
150 /// @param ctx The formatting context provided by \c std::format.
151 /// @return An iterator to the end of the output range.
152 template<typename TContext>
154 TContext& ctx ) const {
155 // Delegate formatting to the std::basic_string_view<TChar> formatter
156 return formatter<std::basic_string_view<TChar>, TChar>::format(
157 static_cast<std::basic_string_view<TChar>>(str), ctx);
158 }
159};
160
161} // namespace [std]
162
163//##################################################################################################
164//################################# std::formatter<alib::Appendable> ###############################
165//##################################################################################################
166
167#if DOXYGEN
169#else
170namespace alib::strings {
171#endif
172
173/// For this simple templated wrapper struct, a generic specialization of type traits
174/// \c std::formatter exists if the template type \p{TAppendable} has a specialization of
175/// #"AppendableTraits".
176/// In other words, all types which have been #"alib_strings_assembly_ttostring;made appendable"
177/// to class #"TAString", can be wrapped in this type and then used as
178/// arguments of function \c std::format.
179///
180/// \note
181/// Unfortunately, it is not possible with all compilers to generically specialize
182/// \c std::formatter for all appendable types. With some compilers, this leads to an
183/// unresolvable ambiguity for types which have both, a specialization for \c std::formatter
184/// and for #"%AppendableTraits". Therefore, this wrapper has to be used.
185///
186/// @see Chapter #"alib_strings_stdformat" of the Programmer's Manual of the module
187/// \alib_strings_nl.
188///
189/// @tparam TAppendable The type of the wrapped appendable.
190template<typename TAppendable>
192 const TAppendable& appendable; ///< A reference to the wrapped appendable.
193
194 /// Constructor.
195 /// @param pAppendable The wrapped appendable.
196 Appendable(const TAppendable& pAppendable) : appendable{pAppendable} {}
197};
198
199/// C++17 Deduction Guide to construct the type #"APPENDABLES::Appendable".
200/// @tparam TAppendable The type of the wrapped appendable.
201template<typename TAppendable>
202Appendable(const TAppendable& ) -> Appendable<TAppendable> ;
203
204
205} // namespace [alib::strings[::APPENDABLES]]
206
207#if DOXYGEN
209#else
210# if __has_include(<format>)
211namespace std {
212# else
213namespace fmt {
214# endif
215#endif
216
217
218/// This specialization of type traits \c std::formatter enables to format the wrapper type
219/// #"APPENDABLES::Appendable", for all types that have a specialization of #"AppendableTraits".
220///
221/// By deriving from <c>std::formatter<std::basic_string_view<TChar>, TChar></c>,
222/// we leverage the library’s optimized handling for string views, thereby avoiding issues
223/// with non-constexpr functions in the custom formatter path.
224///
225/// @see
226/// - Wrapper type #"APPENDABLES::Appendable"
227/// - Chapter #"alib_strings_stdformat" of the Programmer's Manual of the module
228// \alib_strings_nl.
229/// @tparam TAppendable The type of the value wrapped in type #"%APPENDABLES::Appendable".
230/// @tparam TChar The character type used with the formatting operation.
231template <typename TAppendable, typename TChar>
233struct formatter<alib::strings::Appendable<TAppendable>, TChar>
234 : formatter<std::basic_string_view<TChar>, TChar> {
235 /// Creates an intermediate local string (avoiding dynamic allocation in most cases),
236 /// appends the value wrapped in \p{wrapper} to it, and then delegates formatting to the
237 /// \c std::basic_string_view<TChar> formatter.
238 /// @param wrapper The wrapper containing the appendable to append.
239 /// @param ctx The formatting context.
240 /// @return An end iterator of the output range.
241 template <typename FormatContext>
242 auto format(const alib::strings::Appendable<TAppendable>& wrapper,
243 FormatContext& ctx) const {
245 buf.Append(wrapper.appendable);
246
247 return formatter<std::basic_string_view<TChar>, TChar>::format(
248 static_cast<std::basic_string_view<TChar>>(buf), ctx);
249 }
250};
251
252} // namespace [std], for doxygen it is [alib::strings::compatibility::std]
253
254// Faking all template specializations of namespace strings for doxygen into namespace
255// strings::APPENDABLES to keep the documentation of namespace string clean!
256#if DOXYGEN
258#else
259namespace alib::strings {
260#endif
261
262/// This struct enables the use of C++20 function \c std::format - and with that any adaptation
263/// of custom types - to be directly appendable to class #"TAString", without the
264/// need of creating an intermediate temporary \c std::string.
265///
266/// For that, this struct stores the format string and a tuple of decayed formatting arguments.
267/// With a corresponding specialization of struct #"AppendableTraits", the formatted
268/// output is produced using C++20's \c std::vformat_to and a <c>std::back_insert_iterator</c>
269/// that appends characters directly to an #"%AString".
270///
271/// \note
272/// C++20 supports formatting only on character types \c char and \c wchar_t.
273/// With that, the specializations of #"AppendableTraits" are likewise
274/// only defined for these concrete character types. If you compile \alib to switch
275/// the default character type, for example, by using configuration macro
276/// #"ALIB_CHARACTERS_SIZEOF_WCHAR" to change the default size
277/// (which is defined by the compiler !), then appending this type \c TStdFormat might
278/// not be available.
279///
280/// \note
281/// For the same reason, the alias definitions of this struct, namely
282/// - alib::StdFormat,
283/// - alib::NStdFormat, and
284/// - alib::WStdFormat
285///
286/// \note
287/// use these explicit character types, instead of the "logical" types #"alib::nchar;2" and
288/// #"alib::wchar;2".
289///
290/// @see Chapter #"alib_strings_stdformat" of the Programmer's Manual of the module
291/// \alib_strings_nl.
292///
293/// @tparam TChar The character type of the #"%TAString" and the format string.
294/// @tparam TArgs Variadic template parameters representing the types of the formatting arguments.
295template<typename TChar, typename... TArgs>
297 /// The format string given construction. Will be passed to <c>std::format</c>.
299
300 /// The variadic arguments given construction. Will be passed to <c>std::format</c>.
301 std::tuple<std::decay_t<TArgs>...> arguments;
302
303 /// Constructor. Uses perfect forwarding and stores decayed copies of the arguments.
304 /// @param formatString Stored in #".format".
305 /// @param args Stored in #".arguments".
306 TStdFormat(const TString<TChar>& formatString, TArgs&&... args)
307 : format(formatString)
308 , arguments(std::make_tuple(std::forward<TArgs>(args)...)) {}
309};
310
311
312/// C++17 Deduction Guide to construct the type #"APPENDABLES::TStdFormat".
313/// @tparam TChar The character type of the target \c std::string.
314/// @tparam TArgs The types of the variadic formatter arguments.
315template<typename TChar, typename... TArgs>
316TStdFormat(TString<TChar>, TArgs&&...) -> TStdFormat<TChar, TArgs...>;
317
318/// Specialization of the functor #"AppendableTraits" for the type
319/// #"TStdFormat;TStdFormat<char>".
320template<typename TAllocator, typename... Args>
321struct AppendableTraits<TStdFormat<char, Args...> ,char,TAllocator> {
322 /// The functor operator.
323 /// @param target The target string-buffer.
324 /// @param fmtpackage The packaged argumentds to \c std::format.
326 const TStdFormat<char, Args...>& fmtpackage ) {
327 std::back_insert_iterator<TAString<char, TAllocator>> it(target);
328
329 #if __has_include(<format>)
330 namespace f_temp=std;
331 #else
332 namespace f_temp=fmt;
333 #endif
334
335 // Use std::apply to expand the tuple and pass each argument to make_format_args.
336 std::apply( [&](auto&&... a) {
337 f_temp::vformat_to(it, fmtpackage.format,
338 f_temp::make_format_args(static_cast<const decltype(a)&>(a)...));
339 },
340 fmtpackage.arguments );
341 }
342};
343
344/// Specialization of the functor #"AppendableTraits" for the type
345/// #"TStdFormat;TStdFormat<wchar_t>".
346template<typename TAllocator, typename... Args>
347struct AppendableTraits<TStdFormat<wchar_t, Args...> ,wchar_t,TAllocator> {
348 /// The functor operator.
349 /// @param target The target string-buffer.
350 /// @param fmtpackage The packaged argumentds to \c std::format.
352 const TStdFormat<wchar_t, Args...>& fmtpackage ) {
353 std::back_insert_iterator<TAString<wchar_t, TAllocator>> it(target);
354
355 // Use std::apply to expand the tuple and pass each argument to make_format_args.
356 std::apply( [&](auto&&... a) {
357 // Cast each argument to a const lvalue reference.
358 vformat_to(it, fmtpackage.format,
359 make_wformat_args(static_cast<const decltype(a)&>(a)...));
360 },
361 fmtpackage.arguments
362 );
363 }
364};
365
366} // namespace [alib::strings]
367
368namespace alib {
369
370 /// Type alias in namespace #"%alib".
371 template<typename... Args>
372 using StdFormat= strings::TStdFormat<character, Args...>;
373
374 /// Type alias in namespace #"%alib".
375 template<typename... Args>
376 using NStdFormat= strings::TStdFormat<char, Args...>;
377
378 /// Type alias in namespace #"%alib".
379 template<typename... Args>
380 using WStdFormat= strings::TStdFormat<wchar_t, Args...>;
381
382 /// Type alias in namespace #"%alib".
383 template<typename TAppendable>
384 using Appendable= strings::Appendable<TAppendable>;
385}
TAString & Append(const TCharSrc *src, integer srcLength)
Definition tastring.hpp:782
Definition alox.cpp:14
strings::TStdFormat< wchar_t, Args... > WStdFormat
Type alias in namespace #"%alib".
strings::TStdFormat< character, Args... > StdFormat
Type alias in namespace #"%alib".
strings::TStdFormat< char, Args... > NStdFormat
Type alias in namespace #"%alib".
characters::character character
Type alias in namespace #"%alib".
strings::Appendable< TAppendable > Appendable
Type alias in namespace #"%alib".
void operator()(TAString< char, TAllocator > &target, const TStdFormat< char, Args... > &fmtpackage)
void operator()(TAString< wchar_t, TAllocator > &target, const TStdFormat< wchar_t, Args... > &fmtpackage)
Appendable(const TAppendable &pAppendable)
const TAppendable & appendable
A reference to the wrapped appendable.
TString< TChar > format
The format string given construction. Will be passed to std::format.
std::tuple< std::decay_t< TArgs >... > arguments
The variadic arguments given construction. Will be passed to std::format.
TStdFormat(const TString< TChar > &formatString, TArgs &&... args)
auto format(const alib::strings::Appendable< TAppendable > &wrapper, FormatContext &ctx) const
auto format(const alib::strings::TAString< TChar, TAllocator > &str, TContext &ctx) const
auto format(const alib::strings::TCString< TChar > &str, TContext &ctx) const
auto format(const alib::strings::TLocalString< TChar, TCapacity, TAllocator > &str, TContext &ctx) const
auto format(const alib::strings::TString< TChar > &str, TContext &ctx) const
auto format(const alib::strings::TSubstring< TChar > &str, TContext &ctx) const