2021年3月31日星期三

Can trim of a string be done inplace with C++20 ranges?

Inspired by cute cppreference example of trim with C++20 I have written the following code(I have changed the return type to void and arg to std::string& since my "problem"(I am inventing problems to learn C++20) does not exist in original code that uses std::string_view arg and returns std::string).

void trim(std::string&  in)  {      auto view          = std::views::all(in)          | std::views::drop_while(isspace)          | std::views::reverse          | std::views::drop_while(isspace)          | std::views::reverse;          std::string result{view.begin(), view.end()};          in = std::move(result);  }  

Issue here is that this is not inplace, meaning that new string is created. I can write uglier code that does this inplace and I know that traditionally C++ algorithms have no idea that containers exist, but I wonder if C++20 has some tricks that enable me to do the trim in elegant way, but also inplace.

Here is my ugly inplace trim also(not sure if it works ok, but idea is that it does the trimming inplace):

void trim2(std::string& s) {      // ugly and error prone, but inplace      const auto it1 = std::ranges::find_if_not(s, isspace);      const auto it2 = std::ranges::find_if_not(s.rbegin(), s.rend(), isspace);      const size_t shift = (it1==s.end()) ? 0: std::distance(s.begin(), it1);      const size_t result_size = s.size() - shift - ((it2==s.rend()) ? 0 : std::distance(s.rbegin(), it2));      std::shift_left(s.begin(), s.end(), shift);      s.resize(result_size);  }  

godbolt

edit: originally this question claimed in.assign would be UB, but T.C. corrected me.

https://stackoverflow.com/questions/66897068/can-trim-of-a-string-be-done-inplace-with-c20-ranges April 01, 2021 at 08:46AM

没有评论:

发表评论