ALib C++ Library
Library Version: 2510 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 {
232 std::vector<TChar> result;
233 result.reserve( size_t(length) );
234 const TChar* end= array + length;
235 while( array < end )
236 result.push_back( *array++ );
237 return result;
238 }
239 #endif
240};
241
242/// Specialization of the type trait \alib{characters;ZTArrayTraits} for type
243/// <c>std::vector<TChar></c>:
244/// - Character array data (string data) is allowed to be implicitly accessed.
245/// - The construction from zero-terminated character arrays is defined to be allowed in explicit
246/// fashion only, because \c std::vector is a heavy-weight type which will copy the data to an
247/// allocated buffer.<br>
248/// Note that the zero-termination character is not included in the vector when created from
249/// a zero-terminated character array. The length of the vector will have the lengh of the
250/// source string.
251///
252/// @tparam TChar Template parameter providing the underlying character type.
253/// Restricted to types that satisfy concept \alib{characters;IsCharacter}.
254template<typename TChar>
255requires IsCharacter<TChar>
256struct ZTArrayTraits<std::vector<TChar>, TChar >
257{
258 #if !DOXYGEN
259 static constexpr Policy Access = Policy::Implicit;
260 static constexpr Policy Construction = Policy::ExplicitOnly;
261 static constexpr const TChar* Buffer (std::vector<TChar> const & src) { return src.data() ; }
262 static constexpr integer Length (std::vector<TChar> const & src) { return integer( src.size() ); }
263 static constexpr std::vector<TChar> Construct(const TChar* array, integer length )
264 {
265 std::vector<TChar> result;
266 result.reserve( size_t(length) );
267 const TChar* end= array + length;
268 while( array < end )
269 result.push_back( *array++ );
270 return result;
271 }
272 #endif
273};
274
275// #################################### std::array ######################################
276/// Specialization of the type trait \alib{characters;ArrayTraits} for type
277/// <c>std::array<TChar></c>:
278/// - Character array data (string data) is allowed to be implicitly accessed.
279/// - The type may be implicitly created from character array data.
280///
281/// @tparam TChar Template parameter providing the underlying character type.
282/// Restricted to types that satisfy concept \alib{characters;IsCharacter}.
283template<typename TChar, size_t TLength>
284requires IsCharacter<TChar>
285struct ArrayTraits<std::array<TChar,TLength>, TChar>
286{
287 #if !DOXYGEN
288 static constexpr Policy Access = Policy::Implicit;
289 static constexpr Policy Construction = Policy::NONE;
290 static constexpr const TChar* Buffer (std::array<TChar, TLength> const & src) { return src.data () ; }
291 static constexpr integer Length (std::array<TChar, TLength> const & src) { return integer( src.size() ); }
292 #endif
293};
294
295
296/// Specialization of the type trait \alib{characters;ZTArrayTraits} for type
297/// <c>std::array<TChar></c>:
298/// - Zero-terminated string data is allowed to be explicitly accessed as usually data represented
299/// by type \c std::string_view is not zero-terminated.
300/// - The type may be implicitly created from zero-terminated character arrays.
301///
302/// @tparam TChar Template parameter providing the underlying character type.
303/// Restricted to types that satisfy concept \alib{characters;IsCharacter}.
304template<typename TChar, size_t TLength>
305requires IsCharacter<TChar>
306struct ZTArrayTraits<std::array<TChar, TLength>, TChar>
307{
308 #if !DOXYGEN
309 static constexpr Policy Access = Policy::ExplicitOnly;
310 static constexpr Policy Construction = Policy::NONE;
311 static constexpr const TChar* Buffer (std::array<TChar, TLength> const & src ) { return src.data () ; }
312 static constexpr integer Length (std::array<TChar, TLength> const & src ) { return integer( src.size() ); }
313 #endif
314};
315
316// #################################### std::span ######################################
317/// Specialization of the type trait \alib{characters;ArrayTraits} for type
318/// <c>std::span<const TChar></c>:
319/// - Character array data (string data) is allowed to be implicitly accessed.
320/// - The type may be implicitly created from character array data.
321///
322/// @tparam TChar Template parameter providing the underlying character type.
323/// Restricted to types that satisfy concept \alib{characters;IsCharacter}.
324template<typename TChar>
325requires IsCharacter<TChar>
326struct ArrayTraits<std::span<const TChar>, TChar>
327{
328 #if !DOXYGEN
329 static constexpr Policy Access = Policy::Implicit;
330 static constexpr Policy Construction = Policy::Implicit;
331 static constexpr const TChar* Buffer (std::span<const TChar> const & src) { return src.data () ; }
332 static constexpr integer Length (std::span<const TChar> const & src) { return integer( src.size() ); }
333 static std::span<const TChar> Construct(const TChar* array, integer length ) { return std::span<const TChar>( array, size_t(length) ); }
334 #endif
335};
336
337
338/// Specialization of the type trait \alib{characters;ZTArrayTraits} for type
339/// <c>std::span<const TChar></c>:
340/// - Zero-terminated string data is allowed to be explicitly accessed as usually data represented
341/// by type \c std::span is not zero-terminated.
342/// - The type may be implicitly created from zero-terminated character arrays.
343///
344/// @tparam TChar Template parameter providing the underlying character type.
345/// Restricted to types that satisfy concept \alib{characters;IsCharacter}.
346template<typename TChar>
347requires IsCharacter<TChar>
348struct ZTArrayTraits<std::span<const TChar>, TChar>
349{
350 #if !DOXYGEN
351 static constexpr Policy Access = Policy::ExplicitOnly;
352 static constexpr Policy Construction = Policy::Implicit;
353 static constexpr const TChar* Buffer (std::span<const TChar> const & src ) { return src.data () ; }
354 static constexpr integer Length (std::span<const TChar> const & src ) { return integer( src.size() ); }
355 static std::span<const TChar> Construct(const TChar* array, integer length ) { return std::span<const TChar>( array, size_t(length) ); }
356 #endif
357};
358
359
360#if DOXYGEN
361}} // namespace alib::characters[::compatibility::std]
362#endif
363
364} // namespace [alib::characters]
365
366
367// Suppress conversion of CString and AString to std::string. This rationale for this is
368// documented with ZTArrayTraits<std::basic_string> above.
369#if !DOXYGEN
370namespace alib { namespace strings {
371
372 template<typename TChar> struct NoAutoCastTraits<TCString<TChar> , characters::Policy::ExplicitOnly, std::basic_string<TChar> > : std::true_type {};
373 template<typename TChar, typename TAlloc> struct NoAutoCastTraits<TAString<TChar,TAlloc>, characters::Policy::ExplicitOnly, std::basic_string<TChar> > : std::true_type {};
374}}
375#endif
376
377
378
379// #################################################################################################
380// ########################## std::formatter<alib::strings::xyz> ###############################
381// #################################################################################################
382
383#if DOXYGEN
385#else
386# if __has_include(<format>)
387 namespace std {
388# else
389 namespace fmt {
390# endif
391#endif
392
393
394/// Standard formatter specialization for \alib{strings;TString} for use with \c std::format.
395///
396/// By deriving from <c>std::formatter<std::basic_string_view<TChar>, TChar></c>,
397/// we leverage the library’s optimized handling for string views, thereby avoiding issues
398/// with non-constexpr functions in the custom formatter path.
399/// @see Chapter \ref alib_strings_stdformat of the Programmer's Manual of the module
400// \alib_strings_nl.
401/// @tparam TChar The character type.
402template<typename TChar>
403struct formatter<alib::strings::TString<TChar>, TChar>
404 : formatter<std::basic_string_view<TChar>, TChar> {
405 // No need to override parse() since the base class does the work
406
407 /// This function converts the given \p{str} <c>std::basic_string_view<TChar></c> and
408 /// then calls the base class's formatter, which is fully constexpr-capable.
409 /// @tparam TContext The type of the format context.
410 /// @param str The \alib string to format.
411 /// @param ctx The formatting context provided by \c std::format.
412 /// @return An iterator to the end of the output range.
413 template<typename TContext>
414 auto format(const alib::strings::TString<TChar>& str, TContext& ctx) const {
415 // Delegate formatting to the std::basic_string_view<TChar> formatter
416 return formatter<std::basic_string_view<TChar>, TChar>::format(
417 static_cast<std::basic_string_view<TChar>>(str), ctx);
418 }
419};
420
421/// Standard formatter specialization for \alib{strings;TCString} for use with \c std::format.
422///
423/// By deriving from <c>std::formatter<std::basic_string_view<TChar>, TChar></c>,
424/// we leverage the library’s optimized handling for string views, thereby avoiding issues
425/// with non-constexpr functions in the custom formatter path.
426/// @see Chapter \ref alib_strings_stdformat of the Programmer's Manual of the module
427// \alib_strings_nl.
428/// @tparam TChar The character type.
429template<typename TChar>
430struct formatter<alib::strings::TCString<TChar>, TChar>
431 : formatter<std::basic_string_view<TChar>, TChar> {
432 // No need to override parse() since the base class does the work
433
434 /// This function converts the given \p{str} <c>std::basic_string_view<TChar></c> and
435 /// then calls the base class's formatter, which is fully constexpr-capable.
436 /// @tparam TContext The type of the format context.
437 /// @param str The \alib string to format.
438 /// @param ctx The formatting context provided by \c std::format.
439 /// @return An iterator to the end of the output range.
440 template<typename TContext>
441 auto format(const alib::strings::TCString<TChar>& str, TContext& ctx) const {
442 // Delegate formatting to the std::basic_string_view<TChar> formatter
443 return formatter<std::basic_string_view<TChar>, TChar>::format(
444 static_cast<std::basic_string_view<TChar>>(str), ctx);
445 }
446};
447
448/// Standard formatter specialization for \alib{strings;TAString} for use with \c std::format.
449///
450/// By deriving from <c>std::formatter<std::basic_string_view<TChar>, TChar></c>,
451/// we leverage the library’s optimized handling for string views, thereby avoiding issues
452/// with non-constexpr functions in the custom formatter path.
453/// @see Chapter \ref alib_strings_stdformat of the Programmer's Manual of the module
454// \alib_strings_nl.
455/// @tparam TChar The character type.
456template<typename TChar, typename TAllocator>
457struct formatter<alib::strings::TAString<TChar, TAllocator>, TChar>
458 : formatter<std::basic_string_view<TChar>, TChar> {
459
460 /// This function converts the given \p{str} <c>std::basic_string_view<TChar></c> and
461 /// then calls the base class's formatter, which is fully constexpr-capable.
462 /// @tparam TContext The type of the format context.
463 /// @param str The \alib string to format.
464 /// @param ctx The formatting context provided by \c std::format.
465 /// @return An iterator to the end of the output range.
466 template<typename TContext>
467 auto format(const alib::strings::TAString<TChar, TAllocator>& str, TContext& ctx) const {
468 return formatter<std::basic_string_view<TChar>, TChar>::format(
469 static_cast<std::basic_string_view<TChar>>(str), ctx);
470 }
471};
472
473/// Standard formatter specialization for \alib{strings;TSubstring} for use with \c std::format.
474///
475/// By deriving from <c>std::formatter<std::basic_string_view<TChar>, TChar></c>,
476/// we leverage the library’s optimized handling for string views, thereby avoiding issues
477/// with non-constexpr functions in the custom formatter path.
478/// @see Chapter \ref alib_strings_stdformat of the Programmer's Manual of the module
479// \alib_strings_nl.
480/// @tparam TChar The character type.
481template<typename TChar>
482struct formatter<alib::strings::TSubstring<TChar>, TChar>
483 : formatter<std::basic_string_view<TChar>, TChar> {
484 // No need to override parse() since the base class does the work
485
486 /// This function converts the given \p{str} <c>std::basic_string_view<TChar></c> and
487 /// then calls the base class's formatter, which is fully constexpr-capable.
488 /// @tparam TContext The type of the format context.
489 /// @param str The \alib string to format.
490 /// @param ctx The formatting context provided by \c std::format.
491 /// @return An iterator to the end of the output range.
492 template<typename TContext>
493 auto format(const alib::strings::TSubstring<TChar>& str, TContext& ctx) const {
494 // Delegate formatting to the std::basic_string_view<TChar> formatter
495 return formatter<std::basic_string_view<TChar>, TChar>::format(
496 static_cast<std::basic_string_view<TChar>>(str), ctx);
497 }
498};
499
500/// Standard formatter specialization for \alib{strings;TLocalString} for use with \c std::format.
501///
502/// By deriving from <c>std::formatter<std::basic_string_view<TChar>, TChar></c>,
503/// we leverage the library’s optimized handling for string views, thereby avoiding issues
504/// with non-constexpr functions in the custom formatter path.
505/// @see Chapter \ref alib_strings_stdformat of the Programmer's Manual of the module
506// \alib_strings_nl.
507/// @tparam TChar The character type.
508template<typename TChar, alib::integer TCapacity, typename TAllocator>
509struct formatter<alib::strings::TLocalString<TChar,TCapacity,TAllocator>, TChar>
510 : formatter<std::basic_string_view<TChar>, TChar> {
511 // No need to override parse() since the base class does the work
512
513 /// This function converts the given \p{str} <c>std::basic_string_view<TChar></c> and
514 /// then calls the base class's formatter, which is fully constexpr-capable.
515 /// @tparam TContext The type of the format context.
516 /// @param str The \alib string to format.
517 /// @param ctx The formatting context provided by \c std::format.
518 /// @return An iterator to the end of the output range.
519 template<typename TContext>
521 TContext& ctx ) const {
522 // Delegate formatting to the std::basic_string_view<TChar> formatter
523 return formatter<std::basic_string_view<TChar>, TChar>::format(
524 static_cast<std::basic_string_view<TChar>>(str), ctx);
525 }
526};
527
528} // namespace [std]
529
530// #################################################################################################
531// ########################### std::formatter<alib::Appendable> ################################
532// #################################################################################################
533
534#if DOXYGEN
536#else
537namespace alib::strings {
538#endif
539
540/// For this simple templated wrapper struct, a generic specialization of type traits
541/// \c std::formatter exists if template type \p{TAppendable} has a specialization of
542/// \alib{strings;AppendableTraits}.
543/// In other words, all types which have been \ref alib_strings_assembly_ttostring "made appendable"
544/// to class \alib{strings;TAString}, can be wrapped in this type and then used as
545/// arguments of function \c std::format.
546///
547/// \note
548/// Unfortunately, it is not possible with all compilers to generically specialize
549/// \c std::formatter for all appendable types. With some compilers, this leads to an
550/// unresolvable ambiguity for types which have both, a specialization for \c std::formatter
551/// and for \b %AppendableTraits. Therefore, this wrapper has to be used.
552///
553/// @see Chapter \ref alib_strings_stdformat of the Programmer's Manual of the module
554/// \alib_strings_nl.
555///
556/// @tparam TAppendable The type of the wrapped appendable.
557template<typename TAppendable>
559 const TAppendable& appendable; ///< A reference to the wrapped appendable.
560
561 /// Constructor.
562 /// @param pAppendable The wrapped appendable.
563 Appendable(const TAppendable& pAppendable) : appendable{pAppendable} {}
564};
565
566/// C++17 Deduction Guide to construct the type \alib{strings::APPENDABLES;Appendable}.
567/// @tparam TAppendable The type of the wrapped appendable.
568template<typename TAppendable>
569Appendable(const TAppendable& ) -> Appendable<TAppendable>;
570
571
572} // namespace [alib::strings[::APPENDABLES]]
573
574#if DOXYGEN
576#else
577# if __has_include(<format>)
578 namespace std {
579# else
580 namespace fmt {
581# endif
582#endif
583
584
585/// This specialization of type traits \c std::formatter enables to format wrapper type
586/// \alib{strings::APPENDABLES;Appendable}, for all types that have a specialization of
587/// \alib{strings;AppendableTraits}.
588///
589/// By deriving from <c>std::formatter<std::basic_string_view<TChar>, TChar></c>,
590/// we leverage the library’s optimized handling for string views, thereby avoiding issues
591/// with non-constexpr functions in the custom formatter path.
592///
593/// @see
594/// - Wrapper type \alib{strings::APPENDABLES;Appendable}
595/// - Chapter \ref alib_strings_stdformat of the Programmer's Manual of the module
596// \alib_strings_nl.
597/// @tparam TAppendable The type of the value wrapped in type \b %Appendable.
598/// @tparam TChar The character type used with the formatting operation.
599template <typename TAppendable, typename TChar>
601struct formatter<alib::strings::Appendable<TAppendable>, TChar>
602 : formatter<std::basic_string_view<TChar>, TChar> {
603 /// Creates an intermediate local string (avoiding dynamic allocation in most cases),
604 /// appends the value wrapped in \p{wrapper} to it, and then delegates formatting to the
605 /// \c std::basic_string_view<TChar> formatter.
606 /// @param wrapper The wrapper containing the appendable to append.
607 /// @param ctx The formatting context.
608 /// @return An end iterator of the output range.
609 template <typename FormatContext>
610 auto format(const alib::strings::Appendable<TAppendable>& wrapper,
611 FormatContext& ctx) const {
613 buf.Append(wrapper.appendable);
614
615 return formatter<std::basic_string_view<TChar>, TChar>::format(
616 static_cast<std::basic_string_view<TChar>>(buf), ctx);
617 }
618};
619
620} // namespace [std], for doxygen it is [alib::strings::compatibility::std]
621
622// Faking all template specializations of namespace strings for doxygen into namespace
623// strings::APPENDABLES to keep the documentation of namespace string clean!
624#if DOXYGEN
626#else
627namespace alib::strings {
628#endif
629
630/// This struct enables the use of C++20 function \c std::format - and with that any adaption
631/// of custom types - to be directly appendable to class \alib{strings;TAString}, without the
632/// need of creating an intermediate temporary \c std::string.
633///
634/// For that, this struct stores the format string and a tuple of decayed formatting arguments.
635/// With a corresponding specialization of struct \alib{strings;AppendableTraits}, the formatted
636/// output is produced using C++20's \c std::vformat_to and a <c>std::back_insert_iterator</c>
637/// that appends characters directly to an \b %AString.
638///
639/// \note
640/// C++20 supports formatting only on character types \c char and \c wchar_t.
641/// With that, the specializations of \alib{strings;AppendableTraits} are likewise
642/// only defined for these concrete character types. If you compile \alib to switch
643/// the default character type, for example, by using compiler symbol
644/// \ref ALIB_CHARACTERS_SIZEOF_WCHAR to change the default size
645/// (which is defined by the compiler !), then appending this type \c TStdFormat might
646/// not be available.
647///
648/// \note
649/// For the same reason, the alias definitions of this struct, namely
650/// - alib::StdFormat,
651/// - alib::NStdFormat, and
652/// - alib::WStdFormat
653///
654/// \note
655/// use these concrete character types, instead of the "logical" types \ref alib::nchar and
656/// \ref alib::wchar.
657///
658/// @see Chapter \ref alib_strings_stdformat of the Programmer's Manual of the module
659/// \alib_strings_nl.
660///
661/// @tparam TChar The character type of the \b %TAString and the format string.
662/// @tparam TArgs Variadic template parameters representing the types of the formatting arguments.
663template<typename TChar, typename... TArgs>
665 /// The format string given construction. Will be passed to <c>std::format</c>.
667
668 /// The variadic arguments given construction. Will be passed to <c>std::format</c>.
669 std::tuple<std::decay_t<TArgs>...> arguments;
670
671 /// Constructor. Uses perfect forwarding and stores decayed copies of the arguments.
672 /// @param formatString Stored in #format.
673 /// @param args Stored in #arguments.
674 TStdFormat(const TString<TChar>& formatString, TArgs&&... args)
675 : format(formatString)
676 , arguments(std::make_tuple(std::forward<TArgs>(args)...)) {}
677};
678
679
680/// C++17 Deduction Guide to construct the type \alib{strings::APPENDABLES;TStdFormat}.
681/// @tparam TChar The character type of the target \c std::string.
682/// @tparam TArgs The types of the variadic formatter arguments.
683template<typename TChar, typename... TArgs>
684TStdFormat(TString<TChar>, TArgs&&...) -> TStdFormat<TChar, TArgs...>;
685
686/// Specialization of the functor \alib{strings;AppendableTraits} for the type
687/// \alib{strings::APPENDABLES;TStdFormat;TStdFormat<char>}.
688template<typename TAllocator, typename... Args>
689struct AppendableTraits<TStdFormat<char, Args...> ,char,TAllocator>
690{
691 /// The functor operator.
692 /// @param target The target string-buffer.
693 /// @param fmtpackage The packaged argumentds to \c std::format.
695 {
696 std::back_insert_iterator<TAString<char, TAllocator>> it(target);
697
698 #if __has_include(<format>)
699 namespace f_temp=std;
700 #else
701 namespace f_temp=fmt;
702 #endif
703
704 // Use std::apply to expand the tuple and pass each argument to make_format_args.
705 std::apply( [&](auto&&... a) {
706 f_temp::vformat_to(it, fmtpackage.format,
707 f_temp::make_format_args(static_cast<const decltype(a)&>(a)...));
708 },
709 fmtpackage.arguments );
710 }
711};
712
713/// Specialization of the functor \alib{strings;AppendableTraits} for the type
714/// \alib{strings::APPENDABLES;TStdFormat;TStdFormat<wchar_t>}.
715template<typename TAllocator, typename... Args>
716struct AppendableTraits<TStdFormat<wchar_t, Args...> ,wchar_t,TAllocator>
717{
718 /// The functor operator.
719 /// @param target The target string-buffer.
720 /// @param fmtpackage The packaged argumentds to \c std::format.
722 {
723 std::back_insert_iterator<TAString<wchar_t, TAllocator>> it(target);
724
725 // Use std::apply to expand the tuple and pass each argument to make_format_args.
726 std::apply(
727 [&](auto&&... a) {
728 // Cast each argument to a const lvalue reference.
729 vformat_to(it, fmtpackage.format,
730 make_wformat_args(static_cast<const decltype(a)&>(a)...));
731 },
732 fmtpackage.arguments
733 );
734 }
735};
736
737} // namespace [alib::strings]
738
739namespace alib {
740
741 /// Type alias in namespace \b alib.
742 template<typename... Args>
743 using StdFormat= strings::TStdFormat<character, Args...>;
744
745 /// Type alias in namespace \b alib.
746 template<typename... Args>
747 using NStdFormat= strings::TStdFormat<char, Args...>;
748
749 /// Type alias in namespace \b alib.
750 template<typename... Args>
751 using WStdFormat= strings::TStdFormat<wchar_t, Args...>;
752
753 /// Type alias in namespace \b alib.
754 template<typename TAppendable>
755 using Appendable= strings::Appendable<TAppendable>;
756}
757
758
759#endif // ALIB_STRINGS
760#endif // H_ALIB_STRINGS_STDSTRINGS
761
762
TAString & Append(const TCharSrc *src, integer srcLength)
Definition tastring.inl:851
integer Length(const TChar *cstring)
Definition functions.inl:91
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