error: no matching function for call to ‘take_view(std::stringstream&, long unsigned int)’
error: no matching function for call to ‘take_view(std::stringstream&, long unsigned int)’
我想从 std::stringstream
中提取最多 N + 1 个字符串。
目前,我有以下代码(需要修复):
#include <iostream>
#include <iomanip>
#include <sstream>
#include <string>
#include <string_view>
#include <vector>
#include <iterator>
#include <ranges>
#include <algorithm>
int main( )
{
const std::string_view sv { " @a hgs -- " };
const size_t expectedTokenCount { 4 };
std::stringstream ss;
ss << sv;
std::vector< std::string > foundTokens;
foundTokens.reserve( expectedTokenCount + 1 );
std::ranges::for_each( std::ranges::take_view { ss, expectedTokenCount + 1 }, [ &foundTokens ]( const std::string& token )
{
std::back_inserter( foundTokens );
} );
if ( foundTokens.size( ) == expectedTokenCount )
{
// do something
}
for ( const auto& elem : foundTokens )
{
std::cout << std::quoted( elem ) << '\n';
}
}
我该如何解决?另外,我应该如何使用 back_inserter
将提取的字符串 push_back
转换为 foundTokens
?
请注意,以下别名有效:
namespace views = std::views;
namespace rng = std::ranges;
这里有一些问题和奇怪之处。首先:
std::ranges::take_view { ss, expectedTokenCount + 1 }
常规使用std::views
API:
ss | views::take(expectedTokenCount + 1)
这里更明显的问题是 ss
不是视图或范围。您需要创建一个正确的视图:
auto tokens = views::istream<std::string>(ss) | views::take(expectedTokenCount + 1);
现在是另一个问题:
std::back_inserter( foundTokens );
这是一个no-op。它为容器创建一个 back-inserter,它是一个迭代器,其迭代导致 push_back
被调用,但随后不使用它。
虽然在 C++20 中从范围或视图创建向量的情况很差,但这是一种方法:
rng::copy(tokens, std::back_inserter(foundTokens));
将所有这些放在一起,您可以看到一个 live example,但请注意,它可能不是 100% 正确的——它目前使用 GCC 编译,而不是使用 Clang。
如下所述,如果标记之间存在一致的分隔符,您还可以使用 views::split
直接拆分源字符串:
std::string_view delim = " ";
auto tokens = views::split(sv, delim);
但是,如果您的标准库没有实现 this defect report,您可能 运行 会遇到麻烦 this defect report。
我想从 std::stringstream
中提取最多 N + 1 个字符串。
目前,我有以下代码(需要修复):
#include <iostream>
#include <iomanip>
#include <sstream>
#include <string>
#include <string_view>
#include <vector>
#include <iterator>
#include <ranges>
#include <algorithm>
int main( )
{
const std::string_view sv { " @a hgs -- " };
const size_t expectedTokenCount { 4 };
std::stringstream ss;
ss << sv;
std::vector< std::string > foundTokens;
foundTokens.reserve( expectedTokenCount + 1 );
std::ranges::for_each( std::ranges::take_view { ss, expectedTokenCount + 1 }, [ &foundTokens ]( const std::string& token )
{
std::back_inserter( foundTokens );
} );
if ( foundTokens.size( ) == expectedTokenCount )
{
// do something
}
for ( const auto& elem : foundTokens )
{
std::cout << std::quoted( elem ) << '\n';
}
}
我该如何解决?另外,我应该如何使用 back_inserter
将提取的字符串 push_back
转换为 foundTokens
?
请注意,以下别名有效:
namespace views = std::views;
namespace rng = std::ranges;
这里有一些问题和奇怪之处。首先:
std::ranges::take_view { ss, expectedTokenCount + 1 }
常规使用std::views
API:
ss | views::take(expectedTokenCount + 1)
这里更明显的问题是 ss
不是视图或范围。您需要创建一个正确的视图:
auto tokens = views::istream<std::string>(ss) | views::take(expectedTokenCount + 1);
现在是另一个问题:
std::back_inserter( foundTokens );
这是一个no-op。它为容器创建一个 back-inserter,它是一个迭代器,其迭代导致 push_back
被调用,但随后不使用它。
虽然在 C++20 中从范围或视图创建向量的情况很差,但这是一种方法:
rng::copy(tokens, std::back_inserter(foundTokens));
将所有这些放在一起,您可以看到一个 live example,但请注意,它可能不是 100% 正确的——它目前使用 GCC 编译,而不是使用 Clang。
如下所述,如果标记之间存在一致的分隔符,您还可以使用 views::split
直接拆分源字符串:
std::string_view delim = " ";
auto tokens = views::split(sv, delim);
但是,如果您的标准库没有实现 this defect report,您可能 运行 会遇到麻烦 this defect report。