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