ALib C++ Library
Library Version: 2511 R0
Documentation generated by doxygen
Loading...
Searching...
No Matches
ALib.Compatibility.StdStrings.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 \ref mainpage_license "Boost Software License".
7//==================================================================================================
8#ifndef H_ALIB_STRINGS_STDSTRINGS
9#define H_ALIB_STRINGS_STDSTRINGS
10#pragma once
11#ifndef INL_ALIB
12# include "alib/alib.inl"
13#endif
14
15#if ALIB_STRINGS
16#include <string>
17#include <string_view>
18#if __has_include(<format>)
19# include <format>
20#else
21# include <fmt/format.h>
22#endif
23
24#include <span>
25#include <array>
26#include <vector>
27#include "ALib.Lang.H"
28#include "ALib.Strings.H"
29
30
31
32//##################################################################################################
33//###################################### ArrayTraits<std::xyz> #####################################
34//##################################################################################################
35
36namespace alib::characters {
37#if DOXYGEN
38/// This namespace contains sub-namespaces that provide compatibility of 3rd-party types and
39/// module \alib_characters_nl.<br>
40/// The entities of those namespaces become available with the inclusion of specific headers
41/// that import a certain C++20 Module or inject the functionality into a namespace in a
42/// traditional fashion, for example, header \implude{Compatibility.StdStrings}.
43namespace compatibility {
44
45/// This namespace documents compatibility features of \alib_characters_nl and the
46/// standard C++ class library found in namespace \c std.
47namespace std {
48#endif
49
50//######################################### std::string_view #######################################
51/// Specialization of the type trait \alib{characters;ArrayTraits} for type
52/// <c>std::basic_string_view<TChar></c>:
53/// - Character array data (string data) is allowed to be implicitly accessed.
54/// - The type may be implicitly created from character array data.
55///
56/// @tparam TChar Template parameter providing the underlying character type.
57/// Restricted to types that satisfy concept \alib{characters;IsCharacter}.
58template<typename TChar>
59requires IsCharacter<TChar>
60struct ArrayTraits<std::basic_string_view<TChar>, TChar>
61{
62 #if !DOXYGEN
63 static constexpr Policy Access = Policy::Implicit;
64 static constexpr Policy Construction = Policy::Implicit;
65 static constexpr const TChar* Buffer (std::basic_string_view<TChar> const & src) { return src.data () ; }
66 static constexpr integer Length (std::basic_string_view<TChar> const & src) { return integer( src.length() ); }
67 constexpr static std::basic_string_view<TChar> Construct(const TChar* array, integer length ) { return std::basic_string_view<TChar>( array, size_t(length) ); }
68 #endif
69};
70
71/// Specialization of the type trait \alib{characters;ArrayTraits} for type
72/// <c>std::basic_string_view<char8_t></c>:
73/// - Character array data (string data) is allowed to be implicitly accessed.
74/// - The type may be implicitly created from character array data.
75template<>
76struct ArrayTraits<std::basic_string_view<char8_t>, nchar>
77{
78 #if !DOXYGEN
79 static constexpr Policy Access = Policy::Implicit;
80 static constexpr Policy Construction = Policy::Implicit;
81 static const nchar* Buffer (std::basic_string_view<char8_t> const & src) { return reinterpret_cast<const nchar*>(src.data ()) ; }
82 static constexpr integer Length (std::basic_string_view<char8_t> const & src) { return integer( src.length() ); }
83 static std::basic_string_view<char8_t> Construct(const nchar* array, integer length )
84 { return std::basic_string_view<char8_t>( reinterpret_cast<const char8_t*>(array), size_t(length) ); }
85 #endif
86};
87
88/// Specialization of the type trait \alib{characters;ZTArrayTraits} for type
89/// <c>std::basic_string_view<TChar></c>:
90/// - Zero-terminated string data is allowed to be explicitly accessed as usually data represented
91/// by type \c std::string_view is not zero-terminated.
92/// - The type may be implicitly created from zero-terminated character arrays.
93///
94/// @tparam TChar Template parameter providing the underlying character type.
95/// Restricted to types that satisfy concept \alib{characters;IsCharacter}.
96template<typename TChar>
97requires IsCharacter<TChar>
98struct ZTArrayTraits<std::basic_string_view<TChar>, TChar>
99{
100 #if !DOXYGEN
101 static constexpr Policy Access = Policy::ExplicitOnly;
102 static constexpr Policy Construction = Policy::Implicit;
103 static constexpr const TChar* Buffer (std::basic_string_view<TChar> const & src ) { return src.data () ; }
104 static constexpr integer Length (std::basic_string_view<TChar> const & src ) { return integer( src.length() ); }
105 static constexpr std::basic_string_view<TChar> Construct(const TChar* array, integer length ) { return std::basic_string_view<TChar>( array, size_t(length) ); }
106 #endif
107};
108
109/// Specialization of the type trait \alib{characters;ZTArrayTraits} for type
110/// <c>std::basic_string_view<char8_t></c>:
111/// - Zero-terminated string data is allowed to be explicitly accessed as usually data represented
112/// by type \c std::string_view is not zero-terminated.
113/// - The type may be implicitly created from zero-terminated character arrays.
114template<>
115struct ZTArrayTraits<std::basic_string_view<char8_t>, nchar>
116{
117 #if !DOXYGEN
118 static constexpr Policy Access = Policy::ExplicitOnly;
119 static constexpr Policy Construction = Policy::Implicit;
120 static const nchar* Buffer (std::basic_string_view<char8_t> const & src ) { return reinterpret_cast<const nchar*>(src.data ()) ; }
121 static constexpr integer Length (std::basic_string_view<char8_t> const & src ) { return integer( src.length() ); }
122 static std::basic_string_view<char8_t> Construct(const nchar* array, integer length )
123 { return std::basic_string_view<char8_t>( reinterpret_cast<const char8_t*>(array), size_t(length) ); }
124 #endif
125};
126
127//########################################### std::string ##########################################
128
129/// Specialization of the type trait \alib{characters;ArrayTraits} for type
130/// <c>std::basic_string<TChar></c>:
131/// - Character array data (string data) is allowed to be implicitly accessed.
132/// - The construction from character arrays is defined to be allowed in explicit fashion only,
133/// because \c std::string is a heavy-weight string type that will copy the data to an allocated
134/// buffer.
135///
136/// @tparam TChar Template parameter providing the underlying character type.
137/// Restricted to types that satisfy concept \alib{characters;IsCharacter}.
138template<typename TChar>
139requires IsCharacter<TChar>
140struct ArrayTraits<std::basic_string<TChar>, TChar>
141{
142 #if !DOXYGEN
143 static constexpr Policy Access = Policy::Implicit;
144 static constexpr Policy Construction = Policy::ExplicitOnly;
145 static constexpr const TChar* Buffer ( std::basic_string<TChar> const & src ) { return src.data () ; }
146 static constexpr integer Length ( std::basic_string<TChar> const & src ) { return integer( src.length() ); }
147 static constexpr std::basic_string<TChar> Construct( const TChar* array, integer length ) { return std::basic_string<TChar>( array, size_t(length) ); }
148 #endif
149};
150
151/// Specialization of the type trait \alib{characters;ArrayTraits} for type
152/// <c>std::basic_string<char8_t></c>:
153/// - Character array data (string data) is allowed to be implicitly accessed.
154/// - The construction from character arrays is defined to be allowed in explicit fashion only,
155/// because \c std::string is a heavy-weight string type that will copy the data to an allocated
156/// buffer.
157template<>
158struct ArrayTraits<std::basic_string<char8_t>, nchar>
159{
160 #if !DOXYGEN
161 static constexpr Policy Access = Policy::Implicit;
162 static constexpr Policy Construction = Policy::ExplicitOnly;
163 static const nchar* Buffer ( std::basic_string<char8_t> const & src ) { return reinterpret_cast<const nchar*>(src.data()); }
164 static constexpr integer Length ( std::basic_string<char8_t> const & src ) { return integer( src.length() ); }
165 static std::basic_string<char8_t> Construct( const nchar* array, integer length )
166 { return std::basic_string<char8_t>( reinterpret_cast<const char8_t*>(array), size_t(length) ); }
167 #endif
168};
169
170
171
172/// Specialization of the type trait \alib{characters;ZTArrayTraits} for type
173/// <c>std::basic_string<TChar></c>:
174/// - Zero-terminated character string data is allowed to be implicitly accessed, because the
175/// type's buffer access method \c data() returns zero-terminated strings and is defined \c const.
176/// - The type may be created from character array data in an explicit fashion only, because it is a
177/// heavy-weight string type that will copy the data to an allocated buffer.
178///
179/// \note
180/// In combination with classes \alib{strings;TCString;CString} and \alib{strings;TAString;AString},
181/// explicit creation is suppressed using the type trait \alib{strings;NoAutoCastTraits}, because
182/// otherwise an ambiguity would occur due to their ability to implicitly cast to
183/// <c>const char*</c>, which implicitly constructs \c std::string in turn.
184/// This leads to the bad situation that an explicit construction like this:
185///
186/// std::string stdString( cString );
187///
188/// uses the implicit cast to <c>const char*</c> and with that constructs the \c std::string.
189/// This would be inefficient, as the length of the string has to be determined internally.
190///
191/// The most efficient way to create a \c std::string object from an object of type \b CString
192/// or \b AString is to use the explicit constructor:
193///
194/// std::string stdString( String.Buffer(), String.Length() );
195///
196/// @tparam TChar Template parameter providing the underlying character type.
197/// Restricted to types that satisfy concept \alib{characters;IsCharacter}.
198template<typename TChar>
199requires IsCharacter<TChar>
200struct ZTArrayTraits<std::basic_string<TChar>, TChar>
201{
202 #if !DOXYGEN
203 static constexpr Policy Access = Policy::Implicit;
204 static constexpr Policy Construction = Policy::ExplicitOnly;
205 static constexpr const TChar* Buffer ( std::basic_string<TChar> const & src ) { return src.data () ; }
206 static constexpr integer Length ( std::basic_string<TChar> const & src ) { return integer( src.length() ); }
207 static constexpr std::basic_string<TChar> Construct( const TChar* array, integer length ) { return std::basic_string<TChar>( array, size_t(length) ); }
208 #endif
209};
210
211
212//######################################## std::vector<char> #######################################
213/// Specialization of the type trait \alib{characters;ArrayTraits} for type <c>std::vector<TChar></c>:
214/// - Character array data (string data) is allowed to be implicitly accessed.
215/// - The construction from character arrays is defined to be allowed in explicit fashion only,
216/// because \c std::vector is a heavy-weight type which will copy the data to an allocated
217/// buffer.
218///
219/// @tparam TChar Template parameter providing the underlying character type.
220/// Restricted to types that satisfy concept \alib{characters;IsCharacter}.
221template<typename TChar>
222requires IsCharacter<TChar>
223struct ArrayTraits<std::vector<TChar>, TChar>
224{
225 #if !DOXYGEN
226 static constexpr Policy Access = Policy::Implicit;
227 static constexpr Policy Construction = Policy::ExplicitOnly;
228 static constexpr const TChar* Buffer (std::vector<TChar> const & src) { return src.data() ; }
229 static constexpr integer Length (std::vector<TChar> const & src) { return integer( src.size() ); }
230 static std::vector<TChar> Construct(const TChar* array, integer length ) {
231 std::vector<TChar> result;
232 result.reserve( size_t(length) );
233 const TChar* end= array + length;
234 while( array < end )
235 result.push_back( *array++ );
236 return result;
237 }
238 #endif
239};
240
241/// Specialization of the type trait \alib{characters;ZTArrayTraits} for type
242/// <c>std::vector<TChar></c>:
243/// - Character array data (string data) is allowed to be implicitly accessed.
244/// - The construction from zero-terminated character arrays is defined to be allowed in explicit
245/// fashion only, because \c std::vector is a heavy-weight type which will copy the data to an
246/// allocated buffer.<br>
247/// Note that the zero-termination character is not included in the vector when created from
248/// a zero-terminated character array. The length of the vector will have the lengh of the
249/// source string.
250///
251/// @tparam TChar Template parameter providing the underlying character type.
252/// Restricted to types that satisfy concept \alib{characters;IsCharacter}.
253template<typename TChar>
254requires IsCharacter<TChar>
255struct ZTArrayTraits<std::vector<TChar>, TChar >
256{
257 #if !DOXYGEN
258 static constexpr Policy Access = Policy::Implicit;
259 static constexpr Policy Construction = Policy::ExplicitOnly;
260 static constexpr const TChar* Buffer (std::vector<TChar> const & src) { return src.data() ; }
261 static constexpr integer Length (std::vector<TChar> const & src) { return integer( src.size() ); }
262 static constexpr std::vector<TChar> Construct(const TChar* array, integer length ) {
263 std::vector<TChar> result;
264 result.reserve( size_t(length) );
265 const TChar* end= array + length;
266 while( array < end )
267 result.push_back( *array++ );
268 return result;
269 }
270 #endif
271};
272
273//############################################ std::array ##########################################
274/// Specialization of the type trait \alib{characters;ArrayTraits} for type
275/// <c>std::array<TChar></c>:
276/// - Character array data (string data) is allowed to be implicitly accessed.
277/// - The type may be implicitly created from character array data.
278///
279/// @tparam TChar Template parameter providing the underlying character type.
280/// Restricted to types that satisfy concept \alib{characters;IsCharacter}.
281template<typename TChar, size_t TLength>
282requires IsCharacter<TChar>
283struct ArrayTraits<std::array<TChar,TLength>, TChar>
284{
285 #if !DOXYGEN
286 static constexpr Policy Access = Policy::Implicit;
287 static constexpr Policy Construction = Policy::NONE;
288 static constexpr const TChar* Buffer (std::array<TChar, TLength> const & src) { return src.data () ; }
289 static constexpr integer Length (std::array<TChar, TLength> const & src) { return integer( src.size() ); }
290 #endif
291};
292
293
294/// Specialization of the type trait \alib{characters;ZTArrayTraits} for type
295/// <c>std::array<TChar></c>:
296/// - Zero-terminated string data is allowed to be explicitly accessed as usually data represented
297/// by type \c std::string_view is not zero-terminated.
298/// - The type may be implicitly created from zero-terminated character arrays.
299///
300/// @tparam TChar Template parameter providing the underlying character type.
301/// Restricted to types that satisfy concept \alib{characters;IsCharacter}.
302template<typename TChar, size_t TLength>
303requires IsCharacter<TChar>
304struct ZTArrayTraits<std::array<TChar, TLength>, TChar>
305{
306 #if !DOXYGEN
307 static constexpr Policy Access = Policy::ExplicitOnly;
308 static constexpr Policy Construction = Policy::NONE;
309 static constexpr const TChar* Buffer (std::array<TChar, TLength> const & src ) { return src.data () ; }
310 static constexpr integer Length (std::array<TChar, TLength> const & src ) { return integer( src.size() ); }
311 #endif
312};
313
314//############################################ std::span ###########################################
315/// Specialization of the type trait \alib{characters;ArrayTraits} for type
316/// <c>std::span<const TChar></c>:
317/// - Character array data (string data) is allowed to be implicitly accessed.
318/// - The type may be implicitly created from character array data.
319///
320/// @tparam TChar Template parameter providing the underlying character type.
321/// Restricted to types that satisfy concept \alib{characters;IsCharacter}.
322template<typename TChar>
323requires IsCharacter<TChar>
324struct ArrayTraits<std::span<const TChar>, TChar>
325{
326 #if !DOXYGEN
327 static constexpr Policy Access = Policy::Implicit;
328 static constexpr Policy Construction = Policy::Implicit;
329 static constexpr const TChar* Buffer (std::span<const TChar> const & src) { return src.data () ; }
330 static constexpr integer Length (std::span<const TChar> const & src) { return integer( src.size() ); }
331 static std::span<const TChar> Construct(const TChar* array, integer length ) { return std::span<const TChar>( array, size_t(length) ); }
332 #endif
333};
334
335
336/// Specialization of the type trait \alib{characters;ZTArrayTraits} for type
337/// <c>std::span<const TChar></c>:
338/// - Zero-terminated string data is allowed to be explicitly accessed as usually data represented
339/// by type \c std::span is not zero-terminated.
340/// - The type may be implicitly created from zero-terminated character arrays.
341///
342/// @tparam TChar Template parameter providing the underlying character type.
343/// Restricted to types that satisfy concept \alib{characters;IsCharacter}.
344template<typename TChar>
345requires IsCharacter<TChar>
346struct ZTArrayTraits<std::span<const TChar>, TChar>
347{
348 #if !DOXYGEN
349 static constexpr Policy Access = Policy::ExplicitOnly;
350 static constexpr Policy Construction = Policy::Implicit;
351 static constexpr const TChar* Buffer (std::span<const TChar> const & src ) { return src.data () ; }
352 static constexpr integer Length (std::span<const TChar> const & src ) { return integer( src.size() ); }
353 static std::span<const TChar> Construct(const TChar* array, integer length ) { return std::span<const TChar>( array, size_t(length) ); }
354 #endif
355};
356
357
358#if DOXYGEN
359}} // namespace alib::characters[::compatibility::std]
360#endif
361
362} // namespace [alib::characters]
363
364
365// Suppress conversion of CString and AString to std::string. This rationale for this is
366// documented with ZTArrayTraits<std::basic_string> above.
367#if !DOXYGEN
368namespace alib { namespace strings {
369template<typename TChar> struct NoAutoCastTraits<TCString<TChar> , characters::Policy::ExplicitOnly, std::basic_string<TChar> > : std::true_type {};
370template<typename TChar, typename TAlloc> struct NoAutoCastTraits<TAString<TChar,TAlloc>, characters::Policy::ExplicitOnly, std::basic_string<TChar> > : std::true_type {};
371}}
372#endif
373
374
375
376//##################################################################################################
377//################################ std::formatter<alib::strings::xyz> ##############################
378//##################################################################################################
379
380#if DOXYGEN
382#else
383# if __has_include(<format>)
384namespace std {
385# else
386namespace fmt {
387# endif
388#endif
389
390
391/// Standard formatter specialization for \alib{strings;TString} for use with \c std::format.
392///
393/// By deriving from <c>std::formatter<std::basic_string_view<TChar>, TChar></c>,
394/// we leverage the library’s optimized handling for string views, thereby avoiding issues
395/// with non-constexpr functions in the custom formatter path.
396/// @see Chapter \ref alib_strings_stdformat of the Programmer's Manual of the module
397// \alib_strings_nl.
398/// @tparam TChar The character type.
399template<typename TChar>
400struct formatter<alib::strings::TString<TChar>, TChar>
401 : formatter<std::basic_string_view<TChar>, TChar> {
402// No need to override parse() since the base class does the work
403
404 /// This function converts the given \p{str} <c>std::basic_string_view<TChar></c> and
405 /// then calls the base class's formatter, which is fully constexpr-capable.
406 /// @tparam TContext The type of the format context.
407 /// @param str The \alib string to format.
408 /// @param ctx The formatting context provided by \c std::format.
409 /// @return An iterator to the end of the output range.
410 template<typename TContext>
411 auto format(const alib::strings::TString<TChar>& str, TContext& ctx) const {
412 // Delegate formatting to the std::basic_string_view<TChar> formatter
413 return formatter<std::basic_string_view<TChar>, TChar>::format(
414 static_cast<std::basic_string_view<TChar>>(str), ctx);
415 }
416};
417
418/// Standard formatter specialization for \alib{strings;TCString} for use with \c std::format.
419///
420/// By deriving from <c>std::formatter<std::basic_string_view<TChar>, TChar></c>,
421/// we leverage the library’s optimized handling for string views, thereby avoiding issues
422/// with non-constexpr functions in the custom formatter path.
423/// @see Chapter \ref alib_strings_stdformat of the Programmer's Manual of the module
424// \alib_strings_nl.
425/// @tparam TChar The character type.
426template<typename TChar>
427struct formatter<alib::strings::TCString<TChar>, TChar>
428 : formatter<std::basic_string_view<TChar>, TChar> {
429// No need to override parse() since the base class does the work
430
431 /// This function converts the given \p{str} <c>std::basic_string_view<TChar></c> and
432 /// then calls the base class's formatter, which is fully constexpr-capable.
433 /// @tparam TContext The type of the format context.
434 /// @param str The \alib string to format.
435 /// @param ctx The formatting context provided by \c std::format.
436 /// @return An iterator to the end of the output range.
437 template<typename TContext>
438 auto format(const alib::strings::TCString<TChar>& str, TContext& ctx) const {
439 // Delegate formatting to the std::basic_string_view<TChar> formatter
440 return formatter<std::basic_string_view<TChar>, TChar>::format(
441 static_cast<std::basic_string_view<TChar>>(str), ctx);
442 }
443};
444
445/// Standard formatter specialization for \alib{strings;TAString} for use with \c std::format.
446///
447/// By deriving from <c>std::formatter<std::basic_string_view<TChar>, TChar></c>,
448/// we leverage the library’s optimized handling for string views, thereby avoiding issues
449/// with non-constexpr functions in the custom formatter path.
450/// @see Chapter \ref alib_strings_stdformat of the Programmer's Manual of the module
451// \alib_strings_nl.
452/// @tparam TChar The character type.
453template<typename TChar, typename TAllocator>
454struct formatter<alib::strings::TAString<TChar, TAllocator>, TChar>
455 : formatter<std::basic_string_view<TChar>, TChar> {
456
457 /// This function converts the given \p{str} <c>std::basic_string_view<TChar></c> and
458 /// then calls the base class's formatter, which is fully constexpr-capable.
459 /// @tparam TContext The type of the format context.
460 /// @param str The \alib string to format.
461 /// @param ctx The formatting context provided by \c std::format.
462 /// @return An iterator to the end of the output range.
463 template<typename TContext>
464 auto format(const alib::strings::TAString<TChar, TAllocator>& str, TContext& ctx) const {
465 return formatter<std::basic_string_view<TChar>, TChar>::format(
466 static_cast<std::basic_string_view<TChar>>(str), ctx);
467 }
468};
469
470/// Standard formatter specialization for \alib{strings;TSubstring} for use with \c std::format.
471///
472/// By deriving from <c>std::formatter<std::basic_string_view<TChar>, TChar></c>,
473/// we leverage the library’s optimized handling for string views, thereby avoiding issues
474/// with non-constexpr functions in the custom formatter path.
475/// @see Chapter \ref alib_strings_stdformat of the Programmer's Manual of the module
476// \alib_strings_nl.
477/// @tparam TChar The character type.
478template<typename TChar>
479struct formatter<alib::strings::TSubstring<TChar>, TChar>
480 : formatter<std::basic_string_view<TChar>, TChar> {
481// No need to override parse() since the base class does the work
482
483 /// This function converts the given \p{str} <c>std::basic_string_view<TChar></c> and
484 /// then calls the base class's formatter, which is fully constexpr-capable.
485 /// @tparam TContext The type of the format context.
486 /// @param str The \alib string to format.
487 /// @param ctx The formatting context provided by \c std::format.
488 /// @return An iterator to the end of the output range.
489 template<typename TContext>
490 auto format(const alib::strings::TSubstring<TChar>& str, TContext& ctx) const {
491 // Delegate formatting to the std::basic_string_view<TChar> formatter
492 return formatter<std::basic_string_view<TChar>, TChar>::format(
493 static_cast<std::basic_string_view<TChar>>(str), ctx);
494 }
495};
496
497/// Standard formatter specialization for \alib{strings;TLocalString} for use with \c std::format.
498///
499/// By deriving from <c>std::formatter<std::basic_string_view<TChar>, TChar></c>,
500/// we leverage the library’s optimized handling for string views, thereby avoiding issues
501/// with non-constexpr functions in the custom formatter path.
502/// @see Chapter \ref alib_strings_stdformat of the Programmer's Manual of the module
503// \alib_strings_nl.
504/// @tparam TChar The character type.
505template<typename TChar, alib::integer TCapacity, typename TAllocator>
506struct formatter<alib::strings::TLocalString<TChar,TCapacity,TAllocator>, TChar>
507 : formatter<std::basic_string_view<TChar>, TChar> {
508// No need to override parse() since the base class does the work
509
510 /// This function converts the given \p{str} <c>std::basic_string_view<TChar></c> and
511 /// then calls the base class's formatter, which is fully constexpr-capable.
512 /// @tparam TContext The type of the format context.
513 /// @param str The \alib string to format.
514 /// @param ctx The formatting context provided by \c std::format.
515 /// @return An iterator to the end of the output range.
516 template<typename TContext>
518 TContext& ctx ) const {
519 // Delegate formatting to the std::basic_string_view<TChar> formatter
520 return formatter<std::basic_string_view<TChar>, TChar>::format(
521 static_cast<std::basic_string_view<TChar>>(str), ctx);
522 }
523};
524
525} // namespace [std]
526
527//##################################################################################################
528//################################# std::formatter<alib::Appendable> ###############################
529//##################################################################################################
530
531#if DOXYGEN
533#else
534namespace alib::strings {
535#endif
536
537/// For this simple templated wrapper struct, a generic specialization of type traits
538/// \c std::formatter exists if template type \p{TAppendable} has a specialization of
539/// \alib{strings;AppendableTraits}.
540/// In other words, all types which have been \ref alib_strings_assembly_ttostring "made appendable"
541/// to class \alib{strings;TAString}, can be wrapped in this type and then used as
542/// arguments of function \c std::format.
543///
544/// \note
545/// Unfortunately, it is not possible with all compilers to generically specialize
546/// \c std::formatter for all appendable types. With some compilers, this leads to an
547/// unresolvable ambiguity for types which have both, a specialization for \c std::formatter
548/// and for \b %AppendableTraits. Therefore, this wrapper has to be used.
549///
550/// @see Chapter \ref alib_strings_stdformat of the Programmer's Manual of the module
551/// \alib_strings_nl.
552///
553/// @tparam TAppendable The type of the wrapped appendable.
554template<typename TAppendable>
556 const TAppendable& appendable; ///< A reference to the wrapped appendable.
557
558 /// Constructor.
559 /// @param pAppendable The wrapped appendable.
560 Appendable(const TAppendable& pAppendable) : appendable{pAppendable} {}
561};
562
563/// C++17 Deduction Guide to construct the type \alib{strings::APPENDABLES;Appendable}.
564/// @tparam TAppendable The type of the wrapped appendable.
565template<typename TAppendable>
566Appendable(const TAppendable& ) -> Appendable<TAppendable> ;
567
568
569} // namespace [alib::strings[::APPENDABLES]]
570
571#if DOXYGEN
573#else
574# if __has_include(<format>)
575namespace std {
576# else
577namespace fmt {
578# endif
579#endif
580
581
582/// This specialization of type traits \c std::formatter enables to format wrapper type
583/// \alib{strings::APPENDABLES;Appendable}, for all types that have a specialization of
584/// \alib{strings;AppendableTraits}.
585///
586/// By deriving from <c>std::formatter<std::basic_string_view<TChar>, TChar></c>,
587/// we leverage the library’s optimized handling for string views, thereby avoiding issues
588/// with non-constexpr functions in the custom formatter path.
589///
590/// @see
591/// - Wrapper type \alib{strings::APPENDABLES;Appendable}
592/// - Chapter \ref alib_strings_stdformat of the Programmer's Manual of the module
593// \alib_strings_nl.
594/// @tparam TAppendable The type of the value wrapped in type \b %Appendable.
595/// @tparam TChar The character type used with the formatting operation.
596template <typename TAppendable, typename TChar>
598struct formatter<alib::strings::Appendable<TAppendable>, TChar>
599 : formatter<std::basic_string_view<TChar>, TChar> {
600 /// Creates an intermediate local string (avoiding dynamic allocation in most cases),
601 /// appends the value wrapped in \p{wrapper} to it, and then delegates formatting to the
602 /// \c std::basic_string_view<TChar> formatter.
603 /// @param wrapper The wrapper containing the appendable to append.
604 /// @param ctx The formatting context.
605 /// @return An end iterator of the output range.
606 template <typename FormatContext>
607 auto format(const alib::strings::Appendable<TAppendable>& wrapper,
608 FormatContext& ctx) const {
610 buf.Append(wrapper.appendable);
611
612 return formatter<std::basic_string_view<TChar>, TChar>::format(
613 static_cast<std::basic_string_view<TChar>>(buf), ctx);
614 }
615};
616
617} // namespace [std], for doxygen it is [alib::strings::compatibility::std]
618
619// Faking all template specializations of namespace strings for doxygen into namespace
620// strings::APPENDABLES to keep the documentation of namespace string clean!
621#if DOXYGEN
623#else
624namespace alib::strings {
625#endif
626
627/// This struct enables the use of C++20 function \c std::format - and with that any adaption
628/// of custom types - to be directly appendable to class \alib{strings;TAString}, without the
629/// need of creating an intermediate temporary \c std::string.
630///
631/// For that, this struct stores the format string and a tuple of decayed formatting arguments.
632/// With a corresponding specialization of struct \alib{strings;AppendableTraits}, the formatted
633/// output is produced using C++20's \c std::vformat_to and a <c>std::back_insert_iterator</c>
634/// that appends characters directly to an \b %AString.
635///
636/// \note
637/// C++20 supports formatting only on character types \c char and \c wchar_t.
638/// With that, the specializations of \alib{strings;AppendableTraits} are likewise
639/// only defined for these concrete character types. If you compile \alib to switch
640/// the default character type, for example, by using compiler symbol
641/// \ref ALIB_CHARACTERS_SIZEOF_WCHAR to change the default size
642/// (which is defined by the compiler !), then appending this type \c TStdFormat might
643/// not be available.
644///
645/// \note
646/// For the same reason, the alias definitions of this struct, namely
647/// - alib::StdFormat,
648/// - alib::NStdFormat, and
649/// - alib::WStdFormat
650///
651/// \note
652/// use these concrete character types, instead of the "logical" types \ref alib::nchar and
653/// \ref alib::wchar.
654///
655/// @see Chapter \ref alib_strings_stdformat of the Programmer's Manual of the module
656/// \alib_strings_nl.
657///
658/// @tparam TChar The character type of the \b %TAString and the format string.
659/// @tparam TArgs Variadic template parameters representing the types of the formatting arguments.
660template<typename TChar, typename... TArgs>
662 /// The format string given construction. Will be passed to <c>std::format</c>.
664
665 /// The variadic arguments given construction. Will be passed to <c>std::format</c>.
666 std::tuple<std::decay_t<TArgs>...> arguments;
667
668 /// Constructor. Uses perfect forwarding and stores decayed copies of the arguments.
669 /// @param formatString Stored in #format.
670 /// @param args Stored in #arguments.
671 TStdFormat(const TString<TChar>& formatString, TArgs&&... args)
672 : format(formatString)
673 , arguments(std::make_tuple(std::forward<TArgs>(args)...)) {}
674};
675
676
677/// C++17 Deduction Guide to construct the type \alib{strings::APPENDABLES;TStdFormat}.
678/// @tparam TChar The character type of the target \c std::string.
679/// @tparam TArgs The types of the variadic formatter arguments.
680template<typename TChar, typename... TArgs>
681TStdFormat(TString<TChar>, TArgs&&...) -> TStdFormat<TChar, TArgs...>;
682
683/// Specialization of the functor \alib{strings;AppendableTraits} for the type
684/// \alib{strings::APPENDABLES;TStdFormat;TStdFormat<char>}.
685template<typename TAllocator, typename... Args>
686struct AppendableTraits<TStdFormat<char, Args...> ,char,TAllocator>
687{
688 /// The functor operator.
689 /// @param target The target string-buffer.
690 /// @param fmtpackage The packaged argumentds to \c std::format.
692 const TStdFormat<char, Args...>& fmtpackage ) {
693 std::back_insert_iterator<TAString<char, TAllocator>> it(target);
694
695 #if __has_include(<format>)
696 namespace f_temp=std;
697 #else
698 namespace f_temp=fmt;
699 #endif
700
701 // Use std::apply to expand the tuple and pass each argument to make_format_args.
702 std::apply( [&](auto&&... a) {
703 f_temp::vformat_to(it, fmtpackage.format,
704 f_temp::make_format_args(static_cast<const decltype(a)&>(a)...));
705 },
706 fmtpackage.arguments );
707 }
708};
709
710/// Specialization of the functor \alib{strings;AppendableTraits} for the type
711/// \alib{strings::APPENDABLES;TStdFormat;TStdFormat<wchar_t>}.
712template<typename TAllocator, typename... Args>
713struct AppendableTraits<TStdFormat<wchar_t, Args...> ,wchar_t,TAllocator>
714{
715 /// The functor operator.
716 /// @param target The target string-buffer.
717 /// @param fmtpackage The packaged argumentds to \c std::format.
719 const TStdFormat<wchar_t, Args...>& fmtpackage ) {
720 std::back_insert_iterator<TAString<wchar_t, TAllocator>> it(target);
721
722 // Use std::apply to expand the tuple and pass each argument to make_format_args.
723 std::apply(
724 [&](auto&&... a) {
725 // Cast each argument to a const lvalue reference.
726 vformat_to(it, fmtpackage.format,
727 make_wformat_args(static_cast<const decltype(a)&>(a)...));
728 },
729 fmtpackage.arguments
730 );
731 }
732};
733
734} // namespace [alib::strings]
735
736namespace alib {
737
738 /// Type alias in namespace \b alib.
739 template<typename... Args>
740 using StdFormat= strings::TStdFormat<character, Args...>;
741
742 /// Type alias in namespace \b alib.
743 template<typename... Args>
744 using NStdFormat= strings::TStdFormat<char, Args...>;
745
746 /// Type alias in namespace \b alib.
747 template<typename... Args>
748 using WStdFormat= strings::TStdFormat<wchar_t, Args...>;
749
750 /// Type alias in namespace \b alib.
751 template<typename TAppendable>
752 using Appendable= strings::Appendable<TAppendable>;
753}
754
755
756#endif // ALIB_STRINGS
757#endif // H_ALIB_STRINGS_STDSTRINGS
TAString & Append(const TCharSrc *src, integer srcLength)
Definition tastring.inl:828
integer Length(const TChar *cstring)
Definition functions.inl:89
lang::integer integer
Type alias in namespace alib.
Definition integers.inl:149
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