@@ -390,6 +390,16 @@ constexpr size_t strsize(const T (&)[N]) {
390390 return N - 1 ;
391391}
392392
393+ template <typename T>
394+ inline constexpr bool kMaybeStackBufferHasStringType =
395+ std::is_same_v<T, char > || std::is_same_v<T, wchar_t > ||
396+ std::is_same_v<T, char8_t > || std::is_same_v<T, char16_t > ||
397+ std::is_same_v<T, char32_t > || std::is_same_v<T, uint16_t >;
398+
399+ template <typename T>
400+ using MaybeStackBufferStringType =
401+ std::conditional_t <std::is_same_v<T, uint16_t >, char16_t , T>;
402+
393403// Allocates an array of member type T. For up to kStackStorageSize items,
394404// the stack is used, otherwise malloc().
395405template <typename T, size_t kStackStorageSize = 1024 >
@@ -503,9 +513,28 @@ class MaybeStackBuffer {
503513 free (buf_);
504514 }
505515
506- inline std::basic_string<T> ToString () const { return {out (), length ()}; }
507- inline std::basic_string_view<T> ToStringView () const {
508- return {out (), length ()};
516+ // Restrict string helpers to textual element types. libc++ deprecates
517+ // `char_traits<T>` for byte-oriented types like `unsigned char`.
518+ template <typename U = T,
519+ typename Char = MaybeStackBufferStringType<U>>
520+ requires (kMaybeStackBufferHasStringType <U>)
521+ inline std::basic_string<Char> ToString () const {
522+ if constexpr (std::is_same_v<U, Char>) {
523+ return {out (), length ()};
524+ } else {
525+ return {reinterpret_cast <const Char*>(out ()), length ()};
526+ }
527+ }
528+
529+ template <typename U = T,
530+ typename Char = MaybeStackBufferStringType<U>>
531+ requires (kMaybeStackBufferHasStringType <U>)
532+ inline std::basic_string_view<Char> ToStringView () const {
533+ if constexpr (std::is_same_v<U, Char>) {
534+ return {out (), length ()};
535+ } else {
536+ return {reinterpret_cast <const Char*>(out ()), length ()};
537+ }
509538 }
510539 // This can only be used if the buffer contains path data in UTF8
511540 inline std::filesystem::path ToPath () const ;
0 commit comments