0

In C++, suppose I extract lines from a stream, mimicking getline(). Each time I extract a line, using e.g. low-level primitives, I would also like to create a vector of string_views backed by the extracted string. So, essentially, my method would return an extracted string and a vector of string_views backed by the former. How to achieve this? Follows the relevant code snippet:

bool Splitter( istream &is, string &backbone, vector<string_view> &words ) {
    int ch;
    words.clear(), backbone.clear();
    for ( ;(ch= is.get()) != EOF and ch != '\n'; backbone.push_back(ch) ) ;
    int i= 0, j, k= backbone.size();
#define skip_space(i) {for(;i < k and isspace(backbone.at(i)); ++i);}
    skip_space(i);
    assert( i == k or not isspace(backbone.at(i)) );
    for (;i < k; i= j ) {
        for ( j= i+1; j < k and not isspace(backbone.at(j)); ++j ) ;
        assert( j-i > 0 );
        words.emplace_back(backbone.substr(i,j==k?string::npos:j-i)); // <-- how to avoid creating a new string?
        skip_space(j);
    }
#if DBG
    cout << backbone << endl;
    for ( i= 0; i < words.size(); ++i )
        cout << words[i] << ", ";
    cout << endl;
#endif
    return not(ch == EOF and backbone.empty() and words.empty());
}
Ilonpilaaja
  • 1,169
  • 2
  • 15
  • 26

1 Answers1

0

You could wrap backbone in a string_view since its substr() returns a string_view (it also conveniently exposes at()), for example:

    ...
    string_view backbone_view(backbone);
    skip_space(i);
    assert( i == k or not isspace(backbone_view.at(i)) );
    for (;i < k; i= j ) {
        for ( j= i+1; j < k and not isspace(backbone_view.at(j)); ++j ) ;
        assert( j-i > 0 );
        words.emplace_back(backbone_view.substr(i,j==k?string::npos:j-i));
        skip_space(j);
    }
    ...
dms
  • 1,260
  • 7
  • 12