Repository navigation
Build streams.h without std::char_traits<uint8_t> - #27
Merged
Merged
Conversation
The standard only defines std::char_traits for the character types. libc++ 19 removed the generic std::char_traits template, so std::basic_string<uint8_t> no longer compiles. streams.h used it in Value2StringFormatter<uint8_t>, which made every file that includes cpprest/streams.h fail to compile with libc++ 19 or later, including with Xcode 16.3 or later on macOS. Make Value2StringFormatter<uint8_t> return the formatted bytes as a std::string, and have basic_ostream write any formatted string through a private helper. Make the basic_ostream::print overload for strings a template on the traits and allocator, so that calling print on a basic_ostream<uint8_t> does not instantiate std::basic_string<uint8_t>. Printing to a basic_ostream<uint8_t> also no longer stops at an embedded NUL byte. In the stream buffer tests, use std::vector instead of std::basic_string for the data to write, and use rawptr_buffer<char> where a test used rawptr_buffer<std::string>. Fixes #11. Signed-off-by: Gareth Sylvester-Bradley <garethsb@nvidia.com>
Build with the default Xcode on the macos-15 and macos-26 runners, whose libc++ does not define std::char_traits for types other than the character types. Use Homebrew's Boost and OpenSSL, and exclude websockets, because Homebrew's websocketpp is 0.8.2, which does not build with Boost 1.87 or later. Signed-off-by: Gareth Sylvester-Bradley <garethsb@nvidia.com>
garethsb
force-pushed
the
bugfix/libcxx-char-traits
branch
from
November 4, 2026 16:34
2918fcc to
2f3c33d
Compare
GitHub warns that "Due to capacity constraints, jobs targeting macOS arm64 runners may experience longer queue times", and cancelled every macOS job in one run because no runner picked it up. Build Release on macos-15 and Debug on macos-26, rather than both build types on both runners, so that each change waits for fewer macOS runners. Signed-off-by: Gareth Sylvester-Bradley <garethsb@nvidia.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The standard only defines
std::char_traitsfor the character types. libc++ 19 removed the genericstd::char_traitstemplate, sostd::basic_string<uint8_t>no longer compiles.cpprest/streams.hused it inValue2StringFormatter<uint8_t>. As a result, every file that includes that header failed to compile with libc++ 19 or later. That includes the default Xcode on macOS since Xcode 16.3, and Clang with-stdlib=libc++elsewhere.This change avoids
std::basic_string<uint8_t>rather than defining character traits foruint8_t:Value2StringFormatter<uint8_t>returns the formatted bytes as astd::string, andbasic_ostreamwrites any formatted string through a private helper.basic_ostream::printoverload for strings is now a template on the traits and allocator. Callingprinton abasic_ostream<uint8_t>therefore no longer instantiatesstd::basic_string<uint8_t>during overload resolution. Forcharandwchar_tstreams, partial ordering still selects this overload for strings, as before.basic_ostream<uint8_t>no longer stops at an embedded NUL byte, because the bytes are no longer copied throughc_str().std::vectorreplacesstd::basic_stringfor the data to write. One test usedrawptr_buffer<std::string>where it meantrawptr_buffer<char>.The second commit adds macOS jobs to CI, on the
macos-15(Xcode 16.4) andmacos-26(Xcode 26.6) runners, with Homebrew's Boost and OpenSSL. They exclude websockets, because Homebrew's websocketpp is 0.8.2, which does not build with Boost 1.87 or later.Tested locally:
boost::filesystemto find the test libraries. The macOS jobs run the tests.Fixes #11.
The same problem is reported upstream in microsoft#1812. microsoft#1829 fixes it with a separate traits class for
uint8_t, and Homebrew and FreeBSD apply that change as patches. This change is smaller and does not need a traits class.Co-authored-by: Gareth's 🤖 buddy