1

I'm trying to build a view that takes a vector of strings, splits those strings into pieces on char ; and returns permutations for the resulting tokens on each line.

int main()
{
    std::vector<std::string> lines;
    auto strsplit_view = std::ranges::views::split(';') | std::ranges::views::transform([](auto &&rng)
                                                                                        { return std::string_view(&*rng.begin(), std::ranges::distance(rng)); });

    auto filesplit_view = lines |
                          std::ranges::views::transform([&](auto &&line)
                                                        { return line | strsplit_view; });

    for (auto line : filesplit_view)
    {
        do
        {
            print(line);
        } while (std::ranges::next_permutation(line).found)
    }
}

Is there a way of incorporating permutations into the view itself, or do I have to perform a separate loop like shown above?

The current code does not work on lines, what do I have to do in order to pass line into ranges::next_permutation in this case?

Error output:

no matching function for call to ‘std::basic_string_view<char>::basic_string_view(std::ranges::transform_view<std::ranges::split_view<std::ranges::ref_view<std::__cxx11::basic_string<char> >, std::ranges::single_view<char> >, main()::<lambda(auto:18&&)> >&)’
   89 |         } while (std::ranges::next_permutation(std::string_view(line)).found)
Jonas Hjulstad
  • 395
  • 1
  • 8

1 Answers1

3

First, you should not convert the split pieces into std::string_view, because it is non-modifiable, which makes it impossible to use next_permutation. You should return std::span<char>.

Second, filesplit_view is a range whose elements are range adaptors. You need to use a for loop to traverse these range adaptors to get the actual split pieces.

#include <algorithm>
#include <ranges>
#include <string>
#include <vector>

int main() {
  std::vector<std::string> lines;
  auto strsplit_view =
    std::views::split(';') | std::views::transform([](auto rng) {
      return std::span(rng);
    });

  auto filesplit_view = lines | 
    std::views::transform([&](auto&& line) { return line | strsplit_view; });

  for (auto adaptor : filesplit_view) {
    for (auto line : adaptor) {
      do {
        // ...
      } while (std::ranges::next_permutation(line).found);
    }
  }
}

Demo

康桓瑋
  • 33,481
  • 5
  • 40
  • 90
  • This worked just as intended! – Jonas Hjulstad Feb 01 '22 at 13:06
  • I am having trouble compiling this on MSVC 19 /std:c++latest. Compiler doesn't seem to be able to deduce type in the `{ return std::span(rng);}` statement, and also doesn't like `std::ranges::next_permutation(line)` (which perhaps flows from the first error). Is this a MSVC peculiarity? – DS_London Feb 01 '22 at 16:03
  • @DS_London MSVC-trunk [compiles](https://godbolt.org/z/Mor3395fK), It should be because your compiler version has not implemented [P2210](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2210r2.html). – 康桓瑋 Feb 01 '22 at 16:07
  • @康桓瑋 Updated to MSVC 2022 Community, but compiler version only 19.30.30709, compared to 19.31.30818 in your test. Guess I will have to wait for an update. – DS_London Feb 01 '22 at 17:17