SFML: Can't compile `sf::String` with Libc++ 18 due to undefined `std::char_traits`

Can’t compile sf::String with Libc++ 18 due to undefined std::char_traits<std::uint8_t>

The C++ standard library doesn’t define std::char_traits<std::uint8_t>. It used to compile fine with https://github.com/llvm/llvm-project/tree/c0abd3814564a568dfc607c216e6407eaa314f46.

Your environment

Steps to reproduce

cmake -S SFML -B build -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_CXX_FLAGS=-stdlib=libc++
cmake --build build/

Expected behavior

To build just fine.

Actual behavior

This error happens:

In module 'std_string' imported from /home/johel/Documents/C++/Forks/SFML/SFML/include/SFML/System/String.hpp:35:
/home/johel/root/clang-main/bin/../include/c++/v1/string:723:46: error: implicit instantiation of undefined template 'std::char_traits<unsigned char>'
  723 |     static_assert(( is_same<_CharT, typename traits_type::char_type>::value),
      |                                              ^
/home/johel/Documents/C++/Forks/SFML/SFML/src/SFML/System/String.cpp:171:41: note: in instantiation of template class 'std::basic_string<unsigned char>' requested here
  171 | std::basic_string<std::uint8_t> String::toUtf8() const
      |                                         ^
/home/johel/root/clang-main/bin/../include/c++/v1/__fwd/string.h:23:29: note: template is declared here
   23 | struct _LIBCPP_TEMPLATE_VIS char_traits;
      |                             ^

About this issue

  • Original URL
  • State: closed
  • Created 10 months ago
  • Comments: 22 (18 by maintainers)

Most upvoted comments

FWIW even if we temporarily revert the change, that specialization is deprecated and you folks should find a way to move off of it. std::basic_string<uint8_t> is not strictly eStandard C++, that’s the bottom line.

Instead of changing basic_string<uint8_t> to plain string and thus losing the typesystem distinction you worked hard to create in the first place, I would suggest something more like this: https://github.com/Quuxplusone/SFML/commit/alternative-llvm18-string-fix The idea here is simply to define your own sf::char_traits_uint8_t to replace the disappeared std::char_traits<uint8_t>, and then use basic_string<uint8_t, sf::char_traits_uint8_t> everywhere you previously used basic_string<uint8_t>. (I gave it a typedef alias sf::U8String as well; that’s orthogonal to the main idea of the patch, but IMHO the alias is a good idea no matter whether you like the main idea or not.)

IMO the best best outcome would be if you can persuade @philnik777 to revert the libc++18 change that caused this churn… but I don’t claim that that direction is likely to succeed. The question is just how many C++ projects libc++18 is willing to break to make this omelet; I think the answer is probably “lots more than just SFML.”

Now it warns:

[43/252 4 36.926] Building CXX object _deps/sfml-build/src/SFML/System/CMakeFiles/sfml-system.dir/String.cpp.o
In file included from /home/johel/Documents/C++/Forks/SFML/SFML/src/SFML/System/String.cpp:28:
In file included from /home/johel/Documents/C++/Forks/SFML/SFML/include/SFML/System/String.hpp:32:
In file included from /home/johel/Documents/C++/Forks/SFML/SFML/include/SFML/System/Utf.hpp:32:
In file included from /home/johel/Documents/C++/Forks/llvm/libcxx-std-modules/include/c++/v1/locale:200:
In file included from /home/johel/Documents/C++/Forks/llvm/libcxx-std-modules/include/c++/v1/__iterator/istreambuf_iterator.h:14:
In file included from /home/johel/Documents/C++/Forks/llvm/libcxx-std-modules/include/c++/v1/__fwd/istream.h:13:
/home/johel/Documents/C++/Forks/llvm/libcxx-std-modules/include/c++/v1/__fwd/string.h:45:41: warning: 'char_traits<unsigned char>' is deprecated: char_traits<T> for T not equal to char, wchar_t, char8_t, char16_t or char32_t is non-standard and is provided for a temporary period. It will be removed in LLVM 19, so please migrate off of it. [-Wdeprecated-declarations]
   45 | template <class _CharT, class _Traits = char_traits<_CharT>, class _Allocator = allocator<_CharT> >
      |                                         ^
/home/johel/Documents/C++/Forks/SFML/SFML/src/SFML/System/String.cpp:175:10: note: in instantiation of default argument for 'basic_string<std::uint8_t>' required here
  175 |     std::basic_string<std::uint8_t> output;
      |          ^~~~~~~~~~~~~~~~~~~~~~~~~~
/home/johel/Documents/C++/Forks/llvm/libcxx-std-modules/include/c++/v1/__string/char_traits.h:81:8: note: 'char_traits<unsigned char>' has been explicitly marked deprecated here
   81 | struct _LIBCPP_DEPRECATED_("char_traits<T> for T not equal to char, wchar_t, char8_t, char16_t or char32_t is non-standard and is provided for a temporary period. It will be removed in LLVM 19, so please migrate off of it.")
      |        ^
/home/johel/Documents/C++/Forks/llvm/libcxx-std-modules/include/c++/v1/__config:922:53: note: expanded from macro '_LIBCPP_DEPRECATED_'
  922 | #      define _LIBCPP_DEPRECATED_(m) __attribute__((__deprecated__(m)))
      |                                                     ^
1 warning generated.