Mar*_*rkB 2 c++ c++-concepts c++20 std-ranges
std::ranges::range在 C++20 之前,当需要将a 作为参数时,有必要在模板函数中使用转发引用。由于 C++20 中提供了概念,因此现在可以将按std::ranges::view值传递给泛型函数。根据标准,视图是一个范围。
考虑以下代码。
#include <vector>
#include <ranges>
#include <iterator>
#include <iostream>
template <std::ranges::range Range>
void fn1(Range range) // intentionally not a forwarding reference
{
for (auto& elem : range) {
++elem;
}
}
template <std::ranges::view View>
void fn2(View view)
{
for (auto& elem : view) {
++elem;
}
}
int main()
{
std::vector<int> v{1,2,3};
fn1(v); // doesn't increment, since a copy of 'v' is used in 'fn1'.
/* fn2(v); // fails to compile, since 'v' cannot be implicitly converted to a view */
fn1(std::views::all(v)); // increments, since a ref_view is passed to fn1
fn2(std::views::all(v)); // increments, as expected
for (int val : v)
std::cout << val << ' '; // 3 4 5
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我没有什么特别反对转发参考文献的内容。人们可以声称能够直接将一个对范围建模的对象传递到通用函数中(例如fn1(v)),从而提高可读性。
这纯粹是一个偏好问题,还是在决定将通用函数参数实现为Range&&or时还有其他考虑因素View?
从广义上讲,这是一个坏主意。
大多数范围不是视图。这个ranges::view概念要求类型选择成为视图。容器不是视图;而是视图。它们是容器。span是一个视图,但vector不是。此外,大多数容器不能是视图,因为视图要求复制/移动是恒定时间的操作。而对于大多数容器来说,这是不可能的。
因此,通过特定地限制模板view,您基本上可以强制用户将他们传递给函数的任何内容包装在某种视图类型中。这会在调用方产生大量没有任何用处的语法噪音。