通用范围兼容函数
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_iterator
s(支持 operator--
),您不能将 forward_range
的迭代器传递给它。
在使用 compiler that implements P2210 之前没有简单的解决方案。
我有一个对常见类型的标准迭代器进行操作的函数:
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_iterator
s(支持 operator--
),您不能将 forward_range
的迭代器传递给它。
在使用 compiler that implements P2210 之前没有简单的解决方案。