std::to_chars在MacOS/clang上编译但不链接

std::to_chars compile but not linking on MacOS / clang

本文关键字:编译 链接 clang MacOS to chars std      更新时间:2023-10-16

我在使用clang的MacOS下编译项目时遇到问题。

我做到了";精确定位";charconv报头内部的问题:

#include <charconv>
#include <array>
#include <iostream>
int main(){
std::array<char, 64> buffer;
auto[p, ec] = std::to_chars(buffer.begin(), buffer.end(), 123);
if (ec != std::errc() )
std::cout << "error" << 'n';
std::cout << (const char *) buffer.data() << 'n';
}

以下是我如何编译它。

Nikolays-MacBook-Air:~ nmmm$ clang --version
Apple LLVM version 10.0.1 (clang-1001.0.46.4)
Target: x86_64-apple-darwin18.5.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin
Nikolays-MacBook-Air:~ nmmm$ clang -std=c++17 x.cc -lstdc++
Undefined symbols for architecture x86_64:
"std::__1::__itoa::__u32toa(unsigned int, char*)", referenced from:
std::__1::__itoa::__traits_base<unsigned int, void>::__convert(unsigned int, char*) in x-9b1746.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Nikolays-MacBook-Air:~ nmmm$ 

任何帮助都将不胜感激。

更新

我尝试了clang++,但它给了我同样的错误信息。

<charconv>标头包含std::__1::__itoa::__u32toa的声明和使用,该标头中未定义函数。函数在libc++.dylib中定义但是,苹果公司的libc++.dylib的发货频率与它的头文件的发货频率不同;而且,可能更重要的是,libc++直到2018-09-23年才将新符号包含在苹果的"abilist"中,尽管标题更改发生在2018-08-01。因此,在大约53天的时间里,libc++的这一方面在OSX上不起作用。也许苹果在那段时间里把它捡起来并运了出去。

让代码正常工作的一种方法是自己构建libc++。此处的说明,截至2019年末。

$ clang++ -std=c++17 test.cc $ROOT/llvm-project/build/lib/libc++.dylib 
-Wl,-rpath,$ROOT/llvm-project/build/lib
$ ./a.out
123

对于您的问题,一些评论者建议您可以使用GNU libstdc++而不是LLVM libc++来使代码正常工作。这是模糊的事实,但我怀疑为OSX构建libstdc++将比为OSX创建libc++更困难。(后者并不简单!(我不知道在OSX上安装libstdc++的任何方法。有brew install gcc@8,但我敢打赌GCC 8也没有<charconv>

截至2020年初,no供应商(除了最近的微软(提供了<charconv>的完整实现——浮点to_charsfrom_chars很难实现,所以大多数供应商都不提供。("为什么他们不复制现有的实现?"事实证明,<charconv>在任何实现存在之前就已经作为C++17的一部分进行了标准化。没有人想到这会很困难!(

我写了一个很长的答案,然后检查它是否适合我(linux上的clang 9.0.0(。使用clang而不是clang++进行编译。下面的长答案:

Clang的libc++在很长一段时间内都没有完全实现"Elementary string conversions,revision 5"(如to_charsfrom_chars(,有些部分仍然很出色,请参阅此处。但我认为你的应该有效,所以也许你应该更新你的图书馆。

关于to_chars的用法,请考虑,它在字符串末尾显式添加了no。因此,不能仅使用std::cout << (const char *) buffer.data();。您必须使用指针(在代码中命名为p(来标记字符串的末尾。要么通过插入,要么通过生成std::string_view sv(buffer.data(), static_cast<size_t>(p-buffer.data());,要么使用std::copy(buffer.begin(), p, std::ostream_iterator<char>(std::cout, ""));,要么使用太多方法中的另一种。