通用范围兼容函数

Generic ranges-compatible functions

我有一个对常见类型的标准迭代器进行操作的函数:

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

我正在尝试将它与 std::ranges::views 一起使用,但我无法将其迭代器作为输入参数传递给函数:

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

视图迭代器不支持 next_combination 的第二个输入参数 operator+,并且开始和结束迭代器类型不同。

如何调整函数 next_combination 来处理 ranges/views,或者(或者)调整输入参数以进行编译?

编辑:完整示例:

#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; });

}

您使用的gcc版本还没有实现P2210,即views::split(最新标准重命名为views::lazy_split)得到的split subranges可以只能是 forward_range.

由于 next_combination 需要 bidirectional_iterators(支持 operator--),您不能将 forward_range 的迭代器传递给它。

在使用 compiler that implements P2210 之前没有简单的解决方案。