为什么 std::istream_iterator< std::string_view > 无法编译?

dig*_*evo 2 c++ istream-iterator libstdc++ string-view

为什么 GCC 和 Clang 无法编译下面的代码片段(链接)?我想返回 s 的向量std::string_view,但显然无法string_view从 中提取 s stringstream

#include <iostream>
#include <sstream>
#include <string>
#include <string_view>
#include <vector>
#include <iterator>
#include <algorithm>
#include <ranges>


[[ nodiscard ]] std::vector< std::string_view >
tokenize( const std::string_view inputStr, const size_t expectedTokenCount )
{
    std::vector< std::string_view > foundTokens { };

    if ( inputStr.empty( ) ) [[ unlikely ]]
    {
        return foundTokens;
    }

    std::stringstream ss;
    ss << inputStr;

    foundTokens.reserve( expectedTokenCount );

    std::copy( std::istream_iterator< std::string_view >{ ss }, // does not compile
               std::istream_iterator< std::string_view >{ },
               std::back_inserter( foundTokens ) );

    return foundTokens;
}

int main( )
{
    using std::string_view_literals::operator""sv;
    constexpr auto text { "Today is a nice day."sv };

    const auto tokens { tokenize( text, 4 ) };

    std::cout << tokens.size( ) << '\n';
    std::ranges::copy( tokens, std::ostream_iterator< std::string_view >{ std::cout, "\n" } );
}
Run Code Online (Sandbox Code Playgroud)

string_view请注意,用替换 select 实例string可以让代码编译。

tom*_*tom 5

因为and>>上没有运算符(并且需要这个运算符)。std::stringstreamstd::string_viewstd::istream_iterator

正如@tkausl在评论中指出的那样,不可能继续>>工作std::string_view,因为不清楚谁将拥有std::string_view.

对于您的程序,ss << inputStr将字符从inputStrinto复制ss,当ss超出范围时,其内存将被释放。


以下是使用 C++20 的std::ranges::views::split而不是的可能实现std::stringstream。它仅支持单个空格作为分隔符。

#include <iostream>
#include <sstream>
#include <string>
#include <string_view>
#include <vector>
#include <iterator>
#include <algorithm>
#include <ranges>


[[ nodiscard ]] std::vector< std::string_view >
tokenize( const std::string_view inputStr, const size_t expectedTokenCount )
{
    constexpr std::string_view delim { " " };

    std::vector< std::string_view > foundTokens { };

    if ( inputStr.empty( ) ) [[ unlikely ]]
    {
        return foundTokens;
    }

    foundTokens.reserve( expectedTokenCount );
    for ( const auto token : std::views::split( inputStr, delim ) )
    {
        foundTokens.emplace_back( token.begin( ), token.end( ) );
    }

    return foundTokens;
}

int main( )
{
    using std::string_view_literals::operator""sv;
    constexpr auto text { "Today is a nice day."sv };

    const auto tokens { tokenize( text, 4 ) };

    std::cout << tokens.size( ) << '\n';
    std::ranges::copy( tokens, std::ostream_iterator< std::string_view >{ std::cout, "\n" } );
}
Run Code Online (Sandbox Code Playgroud)

这适用于 gcc 12.1(使用 编译-std=c++20),但不适用于 clang 14.0.0,因为 clang 尚未实现P2210