Home > front end >  Generic ranges-compatible functions
Generic ranges-compatible functions

Time:02-02

I have a function that operates on standard iterators of a common type:

template <typename I>
bool next_combination(const I first, I k, const I last)

I'm trying to use it with std::ranges::views, but I'm not able to pass its iterators as input arguments to the function:

auto view = std::ranges::views::split(';') |
        std::ranges::views::transform(
            [](auto &&rng)
            {
            bool ok = next_combination(rng.begin(),rng.begin()   2, rng.end());
            // ...
            }

The view-iterators does not support operator for the second input argument of next_combination, and the begin and end iterator types are different.

How do I adapt function next_combination to handle ranges/views, or (alternatively) adapt the input arguments in order to make this compile?

Edit: Full example:

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

template <typename I>
bool next_combination(const I first, I k, const I last)
{
    /* Credits: Mark Nelson http://marknelson.us */
    if ((first == last) || (first == k) || (last == k))
        return false;
    I i1 = first;
    I i2 = last;
      i1;
    if (last == i1)
        return false;
    i1 = last;
    --i1;
    i1 = k;
    --i2;
    while (first != i1)
    {
        if (*--i1 < *i2)
        {
            I j = k;
            while (!(*i1 < *j))
                  j;
            std::iter_swap(i1, j);
              i1;
              j;
            i2 = k;
            std::rotate(i1, j, last);
            while (last != j)
            {
                  j;
                  i2;
            }
            std::rotate(k, i2, last);
            return true;
        }
    }
    std::rotate(first, k, last);
    return false;
}

int main()
{
    std::string line;
    std::vector<std::string> lines{"bcd;zac", "cad;c"};

    auto strsplit_view =
        std::ranges::views::split(';') | std::ranges::views::drop(1) |
        std::ranges::views::transform(
            [](auto &&rng)
            {
            bool ok = next_combination(rng.begin(),rng.begin()   2, rng.end());
            return std::span(&*rng.begin(), std::ranges::distance(rng)); });

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

}

CodePudding user response:

You are using a version of gcc that has not yet implemented the P2210, that is, the split subranges obtained by views::split (renamed views::lazy_split in the latest standard) can only be a forward_range.

Since next_combination requires bidirectional_iterators (which support operator--), you cannot pass an iterator of forward_range to it.

There is no simple solution until using a compiler that implements P2210.

  •  Tags:  
  • Related