And*_*rew 5 c++ stl compiler-specific c++20 std-ranges
我想用 和 的标记分割字符串std::views::split,并为每个检索到的子字符串调用该std::from_chars函数。这是一个 MRE ( https://godbolt.org/z/1K71qo9s4 ),它在 GCC 上编译成功,但在 MSVC 上编译失败:
#include <iostream>
#include <ranges>
#include <string>
#include <charconv>
int main()
{
std::string source{"10%15%20%35"};
for ( auto i : source | std::views::split('%') )
{
int x;
std::from_chars( i.begin().base(), i.end().base(), x );
std::cout << x << ' ';
}
}
Run Code Online (Sandbox Code Playgroud)
奇怪的是,根据cppreference , P2210R2中的行为std::views::split发生了变化,提供了效果为base()
相当于
return cur_
然后,根据编译器支持页面,P2210R2自 19.31 起 MSVC 支持该示例,因此该示例应该可以工作。
如果这按照您的想法工作,i.begin().base()应该是 a std::string::iterator,它必须const char*(或至少可转换为 a const char*)才能传递给std::from_chars。
看起来 libstdc++ 也没有正确实现这一点,并且i.begin()返回 astd::string::iterator而不是std::ranges::views::split_view<std::string>::iterator. 碰巧 libstdc++有一个名为返回指针的std::string::iterator函数。base()
无论如何,你必须获得一个const char*指针,你可以这样做std::to_address:
std::from_chars( std::to_address(i.begin()), std::to_address(i.end()), x );
Run Code Online (Sandbox Code Playgroud)
或者类似的东西:
std::from_chars( std::ranges::data(i), std::ranges::data(i) + std::ranges::size(i), x );
// Or, since span is constructible from ranges
for (std::span<const char> i : source | std::views::split('%')) {
std::from_chars( i.data(), i.data() + i.size(), x );
Run Code Online (Sandbox Code Playgroud)