此代码有效并从向量返回一个foo{5}迭代器:
struct foo {
int value;
};
auto main() -> int {
auto ints = std::vector<foo>{{3}, {2}, {5}, {6}, {7}, {0}, {4}, {6}};
std::ranges::sort(ints, {}, &foo::value);
auto it = std::upper_bound(
ints.begin(), ints.end(),
4,
[](const int v, const foo f) {
return v < f.value;
}
);
}
Run Code Online (Sandbox Code Playgroud)
然而,这不能编译:
struct foo {
int value;
};
auto main() -> int {
auto ints = std::vector<foo>{{3}, {2}, {5}, {6}, {7}, {0}, {4}, {6}};
std::ranges::sort(ints, {}, &foo::value);
auto it = std::ranges::upper_bound( // …Run Code Online (Sandbox Code Playgroud) 这里写的是std::ranges::size应该返回一个无符号整数。但是,当我在Eigen向量(使用 Eigen 3.4)上使用它时,将进行以下编译:
Eigen::VectorXd x;
static_assert(std::same_as<Eigen::VectorXd::Index,
decltype(std::ranges::size(x))>);
Run Code Online (Sandbox Code Playgroud)
其中Eigen::VectorXd::Index是众所周知的有符号整数。通过查看 的实现std::ranges::size,我注意到返回类型是从 的返回类型推断出来的x.size(),这正是Eigen::VectorXd::Index. 这是一个错误吗std::ranges::size?或者这是预期的?
更新 27/12/2021
上面链接的 C++ 参考页最终更改了该函数的描述std::ranges::size:它只返回一个整数,不一定是无符号的!
请参阅此示例代码:
#include <ranges>
int main() {
for(auto i : std::ranges::iota_view(1) | std::views::reverse)
break;
}
Run Code Online (Sandbox Code Playgroud)
它在 gcc 上编译(我无法检查 clang/msvc - 因为它们不支持范围)。当然——它“永远”运行并且什么也不做。
我还检查了不允许在无限范围内执行std::ranges::rbegin(inf)或操作std::ranges::rend(inf)(它无法编译)。
我不确定这是否是正确的 C++ 代码?我对 std::ranges::reverse 实现很好奇 - 看起来 rbegin/rend 不用于实现此视图 - 那么这个实现是如何工作的?
我使用 SG14flat_map作为容器。
根据标准地图,它采用Key模板Value参数。
然而,与标准映射不同,它不存储std::pair<Key, Value>在二叉搜索树中,而是将键和值存储在两个单独的容器中(附加模板参数默认为std::vector)
template<\n class Key,\n class Mapped,\n class Compare = std::less<Key>,\n class KeyContainer = std::vector<Key>,\n class MappedContainer = std::vector<Mapped>\n>\nclass flat_map\nRun Code Online (Sandbox Code Playgroud)\n然后它定义了许多类型,如下所示:
\nusing key_type = Key;\nusing mapped_type = Mapped;\nusing value_type = std::pair<const Key, Mapped>;\nusing key_compare = Compare;\nusing const_key_reference = typename KeyContainer::const_reference;\nusing mapped_reference = typename MappedContainer::reference;\nusing const_mapped_reference = typename MappedContainer::const_reference;\nusing reference = std::pair<const_key_reference, mapped_reference>;\nusing const_reference = std::pair<const_key_reference, const_mapped_reference>;\nRun Code Online (Sandbox Code Playgroud)\nstd::ranges::find_if如果我尝试在 上使用flat_map,则会收到错误: …
如果我创建一个视图,那么它就是一个范围。这似乎很合理。
\n但是,如果它是 const,那么它就变成非范围:
\n#include <ranges>\n\nint main()\n{\n int values[] = { 1, 2, 3 };\n\n auto odd_values = values | std::views::filter([](int i){ return i % 2; });\n static_assert(std::ranges::range<decltype(odd_values)>);\n\n auto const odd_ref = odd_values; \n static_assert(!std::ranges::range<decltype(odd_ref)>); // WHY NOT?\n}\nRun Code Online (Sandbox Code Playgroud)\n这是令人惊讶的 - 我看不出有任何理由我不应该能够阅读内容,就像我可以从const std::vector.
如果这是一个实现错误,我在 GCC 11 中遇到过这种情况,使用-std=c++20; 库是 libstdc++-11。
如果我添加一个调用,std::ranges::begin()我会得到大量诊断信息,显示它没有找到成员函数,也没有通过 ADL 找到任何内容,然后遇到了阻止std::begin匹配的后备删除函数。
从错误消息来看,我们似乎缺少视图类中的const 版本begin()和成员函数。end()这是预期的结果,还是只是被错过了?
这让我想到了一个更简单的失败示例:
\n#include <ranges>\n\nint main()\n{\n int values[] = …Run Code Online (Sandbox Code Playgroud) 我想使用std::views.
为了按顺序运行,代码如下所示:
int main() {
//pseudo-random numbers
random_device rd;
default_random_engine eng(rd());
uniform_int_distribution<int> distr(0, 100);
auto r = ranges::views::iota(0, 10);
vector<double> v(10, 1);
for_each(r.begin(), r.end(), [&](int i) {v[i] = distr(eng); });
for (auto&& i : v) cout << i << " "; cout << endl;
}
Run Code Online (Sandbox Code Playgroud)
这很好用。我使用的是标准版本std::for_each(),而不是命名空间中的版本ranges,因为它们没有执行策略。现在是并行版本。唯一的区别:
for_each(execution::par, r.begin(), r.end(), [&](int i) {v[i] = distr(eng); });
Run Code Online (Sandbox Code Playgroud)
MSVC 报错:
error C2338: Parallel algorithms require forward iterators or stronger
Run Code Online (Sandbox Code Playgroud)
我在这里发现了类似的问题:Usingranges::view::iota inparallelalgorithm,我实现了那里提供的解决方案:
auto r = views::iota(0) …Run Code Online (Sandbox Code Playgroud) C++23 引入了非常强大的ranges::to从范围构造对象(通常是容器)的功能,具有以下定义([range.utility.conv.to]):
template<class C, input_\xc2\xadrange R, class... Args> requires (!view<C>)\n constexpr C to(R&& r, Args&&... args);\nRun Code Online (Sandbox Code Playgroud)\n请注意,它仅限制模板参数C不是 a view,也就是说,C甚至可能不是 a range。
然而,它的实现用于range_value_t<C>获取 的元素类型C,这C至少使得模板参数必须对 a 进行建模的给range定约束。range_value_tRrange
那么,为什么ranges::to对模板参数的约束如此宽松C?
我注意到论文的 R3 版本过去常常约束C为input_range,这显然是合理的,因为input_range保证了 是range_value_t格式良好的,但在 R4 中这个约束被删除了。而且我没有找到任何关于此更改的评论。
C那么,消除必须的约束有哪些考虑因素呢input_range?
有没有一个实际的例子来说明这种约束放松的好处?
\n目标是在一定范围的输入值上最小化函数。性能很重要。不幸的是,该ranges::min()算法一遍又一遍地重新计算实时最优的输出。
看起来该算法可以缓存与最佳值相对应的输出值,或者我错过了什么?
在这个例子中,为什么f(x=0)需要调用n次呢?
#include <ranges>
#include <algorithm>
#include <stdio.h>
using namespace std;
int main()
{
auto f=[](int x){
printf("calling f(x=%d)\n", x);
return x*x;
};
auto rg = views::iota(0,4);
int x1 = ranges::min(rg, {}, f);
}
Run Code Online (Sandbox Code Playgroud)
它输出:
调用 f(x=0) 调用 f(x=1) 调用 f(x=0) 调用 f(x=2) 调用 f(x=0) 调用 f(x=3)
有没有ranges::min()更优化的调用方式?
最初的问题是为什么使用以下代码,
std::vector<int> coll{1,4,7,10};
auto iseven = [](auto&& i){return i % 2 == 0; };
auto colleven = coll | std::views::filter(iseven);
// first view materialization
for(int& i : colleven)
{
i += 1;
}
for(auto i : coll)
std::cout << i << ' ';
std::cout << std::endl;
// second view materialization
for(int& i : colleven)
{
i += 1;
}
for(auto i : coll)
std::cout << i << ' ';
Run Code Online (Sandbox Code Playgroud)
通过两次具体化视图,我们得到两个不同的结果。乍一看这确实很奇怪。输出:
1 5 7 11
1 6 7 11
Run Code Online (Sandbox Code Playgroud)
经过一些研究并研究潜在的重复项后,我了解到这是 …
什么时候
views::filter([](auto n) { return n % 2 == 0; });已激活,我无法获取[2,4]。views::transform([](auto n) { return 2 * n; });已激活,我成功获得了[2,4,6,8,10]。#include <iostream>
#include <ranges>
#include <sstream>
int main()
{
using namespace std;
auto input = views::iota(1, 5 + 1);
auto output = input |
views::filter([](auto n) { return n % 2 == 0; });
//views::transform([](auto n) { return 2 * n; });
stringstream ss;
ss << "[";
for (auto i = 0; i < output.size() …Run Code Online (Sandbox Code Playgroud) c++ ×10
std-ranges ×10
c++20 ×8
range-v3 ×2
algorithm ×1
c++-concepts ×1
c++23 ×1
eigen ×1
eigen3 ×1
g++ ×1
iterator ×1
min ×1
minimization ×1
projection ×1
visual-c++ ×1