1

I'm using clang 13.0.0 in a CMAKE-based project, CMAKE_CXX_STANDARD is defined as 20. The following code causes a compilation error (no type named 'u8string' in namespace 'std'):

#include <iostream>
#include <string>

int main() {
#ifdef __cpp_char8_t
    std::u8string sss = u8"a";  // <---- this branch is picked up
#else
    std::string sss = "b"
#endif    
return 0;
}

Below is the CMakeLists.txt:

cmake_minimum_required(VERSION 3.20)

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_C_COMPILER clang)
set(CMAKE_CXX_COMPILER clang++)

project(clang_test)

add_executable(clang_test main.cpp)

Am I missing something or is it a clang bug? I mean, if std::u8string is not yet there, the macro shouldn't be defined, right? By the way, if you know the way to undefine it somehow with the CMake, please, share your experience. Here the topic starter faces the same problem, I think, but there is no solution proposed yet.

Update: the platform is RHEL 8.4

Update 2: moved the 'project' call below the compiler settings in the CMakeLists.txt

Anton Pilyak
  • 1,050
  • 2
  • 15
  • 34
  • `I mean, if std::u8string is not yet there, the macro shouldn't be defined, right?` nope. It has partial support for C++20 - enough to allow compiler flag. If one were to wait for full support the macro would be false for a very very long time. They still haven't fully implemented C++17. – ALX23z Nov 10 '21 at 17:04
  • 1
    Which platform/toolchain is this happening on? I can't readily reproduce this. My guess is that clang is picking up an older stdlib from elsewhere on the system. –  Nov 10 '21 at 17:19
  • @ALX23z AFAIK, all modern compilers/stdlibs offer full `char8_t` / `std::u8string` support as of today: https://gcc.godbolt.org/z/8o1j13T1Y –  Nov 10 '21 at 17:26
  • The platform is RHEL8.4. @Frank, don't you know how to check if clang (or CMAKE) picks up an older stdlib from somewhere? Or, at least, how to manually point it to the correct one? – Anton Pilyak Nov 10 '21 at 17:47
  • As far as figuring out which stdlib is being used. A simple but janky way to easily do that is to intentionally cause an error in stdlib templated code and look at the paths in the error log. For example: https://gcc.godbolt.org/z/sG4oT8qz7 –  Nov 10 '21 at 18:07
  • 2
    Depending on how clang-13 was installed, `target_compile_options(clang_test PRIVATE -stdlib=libc++)` might do the trick. –  Nov 10 '21 at 18:09
  • 2
    BTW, setting a compiler **after** the `project` call is wrong. See that my answer for more details: https://stackoverflow.com/a/63944545/3440745. – Tsyvarev Nov 10 '21 at 22:45

1 Answers1

0

Frank's suggestion was correct - the problem is in that Clang was using an older version of libstdc++ and not libc++;

target_compile_options(clang_test PRIVATE -stdlib=libc++) 

fixes the issue for me. Though I don't entirely understand why it doesn't work with libstdc++, if you have any idea, please, share it here - I assume that this is a separate question.

Also, Tsyvarev's point is indeed a very important one, and the compiler should be set before the project call. I've corrected the example in my question.

Update: Finally I understand the reason why it fails: __cpp_char8_t is not sufficient for std::u8string, __cpp_lib_char8_t should be used instead.

Thanks everyone for your help!

Anton Pilyak
  • 1,050
  • 2
  • 15
  • 34