我有这个签名的第三方功能:
std::vector<T> f(T t);
Run Code Online (Sandbox Code Playgroud)
我还有一个已命名的潜在无限范围(范围-v3排序).我想创建一个映射到该范围的所有元素的管道,并将所有向量展平为包含其所有元素的单个范围.T
src
f
本能地,我会写下面的内容.
auto rng = src | view::transform(f) | view::join;
Run Code Online (Sandbox Code Playgroud)
但是,这不起作用,因为我们无法创建临时容器的视图.
range-v3如何支持这样的范围管道?
我正在玩Range-v3库以表现出一种荣耀,find_if
并且好奇为什么谷歌基准测试一直将我的Range-v3代码排序比我的std::find_if
方法更差.g ++和clang都用-O3
和表示相同的模式#define NDEBUG
.
我想到的具体例子是以下使用STL:
std::vector<int> lengths(large_number, random_number);
auto const to_find = std::accumulate(lengths.begin(), lengths.end(), 0l) / 2;
auto accumulated_length = 0l;
auto found = std::find_if(lengths.begin(), lengths.end(), [&](auto const &val) {
accumulated_length += val;
return to_find < accumulated_length;
});
auto found_index = std::distance(lengths.begin(), found);
Run Code Online (Sandbox Code Playgroud)
出于此说明的目的,这有点做作,但通常会有一个随机生成器用于向量中的to_find
变量和随机值lengths
.
使用Range-v3库,我得到以下代码
using namespace ranges;
std::vector<int> lengths(large_number, random_number);
auto const to_find = accumulate(lengths, 0l) / 2;
auto found_index = distance(lengths | view::partial_sum()
| view::take_while([=](auto const i) …
Run Code Online (Sandbox Code Playgroud) 这个“管道”,存储库的主页说,不像范围的使用,即使它看起来一样:它不是基于懒惰的拉动,而是基于急切的推动。但是据说不能使用范围库来执行各种“管道”操作。例如:
我不太明白为什么原则上是这样。(当然,除了无法获得结束迭代器/哨兵的范围。)
以下是代码审查中发现的任务.我想根据特殊类型的比较谓词从集合中选择最小值.像这样:
struct Complex { ... };
float calcReduction(Complex elem);
Complex findMinValueWithPredicates(const std::vector<Complex>& values)
{
auto it = std::min_element(values.begin(), values.end(),
[](const Complex& a, const Complex& b) {
return calcReduction(a) < calcReduction(b);
});
if (it == values.end()) throw std::runtime_error("");
return *it;
}
Run Code Online (Sandbox Code Playgroud)
在这里,我找到了基于谓词的最小元素.此谓词计算两个值的减少,float
然后比较这些浮点数.工作正常,看起来整洁.
你能看到问题吗?是的,对于一组N
元素calcReduction()
称为2N
时间,而它只足以计算它N
- 每个元素一次.
解决此问题的一种方法是编写显式计算:
Complex findMinValueExplicit(const std::vector<Complex>& values)
{
float minReduction = std::numeric_limits<float>::max();
Complex minValue;
for (Complex value : values)
{
float reduction = calcReduction(value);
if (reduction < …
Run Code Online (Sandbox Code Playgroud) 我有一个带有函数的对象来获取开始和结束迭代器:
const_iterator err_begin() const
const_iterator err_end() const
Run Code Online (Sandbox Code Playgroud)
因为他们没有被命名begin
和end
,我不能直接把我的对象在范围-V3功能.
有没有一个简单的包装器可以用来使这个对象与range-v3库一起工作?
例如:
auto hasErrors = !empty(something(x.err_begin(), x.err_end()));
Run Code Online (Sandbox Code Playgroud) 假设我有一个等级向量,其中等级是
struct Grade{
const int grade;
const int ECTS; // weight
};
Run Code Online (Sandbox Code Playgroud)
是否有STL / range-v3算法/算法使我能够做到这一点?
我知道我可以std:: accumulate
用一些花哨的类型作为累加器(记住重量的总和)来做到这一点,但是我正在寻找一个更简单的替代方法(如果存在)。
特定
auto empty_line = [](auto& str){ return str.size() == 0; };
Run Code Online (Sandbox Code Playgroud)
对于那个ranges::getlines
返回拥有 view_facade
其正面迭代器的缓冲区的拥有者的事实.
所以我们有义务在传递算法之前将这种范围变成左值.
auto line_range1 = ranges::getlines(std::cin);
auto iter1 = ranges::find_if_not(line_range1,empty_line);
auto input1 = std::stoi(*iter1);
Run Code Online (Sandbox Code Playgroud)
而且还有一个很酷的保护机制,可以防止所有解除引用迭代器的时间已经被破坏的数据,并使这些尝试编译时错误.
因此,当拥有view_facade
作为rvalue传递给算法时,保护将参与解除引用.
这不会编译.
auto iter2 = ranges::find_if_not(ranges::getlines(std::cin),empty_line);
// at this point the `owning` range destroyed,
// so as the buffer we (should've) hold (before!).
// So this won't compile
// auto input2 = std::stoi(*iter2);
Run Code Online (Sandbox Code Playgroud)
错误为:
<source>:19:29: error: no match for 'operator*' (operand …
Run Code Online (Sandbox Code Playgroud) 从range-v3的文档中:
view::all
返回包含源中所有元素的范围.用于将容器转换为范围.
让我困惑的是:
view::all
使用?std::vector
,std::list
等)在概念上不是范围吗?例如:
auto coll = std::vector{ 1, 2, 2, 3 };
view::all(coll) | view::unique; // version 1
coll | view::unique; // version 2
Run Code Online (Sandbox Code Playgroud)
有什么区别version 1
和version 2
?
假设我们有
cppcoro::generator<int> gen_impl(int in) {
const auto upper = in + 10;
for (; in < upper; ++in)
co_yield in;
}
cppcoro::generator<cppcoro::generator<int>> gen() {
for (int n = 1; n < 100; n += 10)
co_yield gen_impl(n);
}
Run Code Online (Sandbox Code Playgroud)
所以我们可以很好地迭代内部范围
for (auto&& row : gen() ) {
for (auto n : row)
std::cout << n << ' ';
std::cout << '\n';
}
Run Code Online (Sandbox Code Playgroud)
注意:范围是for ref是必需的,因为cppcoro::generator
不允许复制(删除的副本ctor)
打印
1 2 3 4 5 6 7 8 9 10
11 12 13 14 …
Run Code Online (Sandbox Code Playgroud) 对于我的矩阵类,我想在range-v3视图上进行某种运算符重载(可能使用表达式模板)+ - / * %
.例如,如果我想获得两列总和的视图,我想写
col_1 + col_2
Run Code Online (Sandbox Code Playgroud)
代替
rv::zip_with([](auto c1, auto c2) {return c1 + c2;}, col_1, col_2);
Run Code Online (Sandbox Code Playgroud)
可能会使用本文中的一些想法来避免构造太多的临时工.这是我想写的代码:
//simple example
//what I want to write
auto rangeview = col_1 + col_2;
//what I can write
auto rangeview = rv::zip_with([](auto c1, auto c2) {
return c1 + c2;
}, col_1, col_2);
//itermediate
//what I want to write
auto rangeview = col_1 + col_2 + col_3;
//what I can write
auto rangeview = rv::zip_with([](auto c1, auto …
Run Code Online (Sandbox Code Playgroud)