#include <vector>
#include <ranges>
int main()
{
auto v = std::vector{1, 2, 3, 4};
v | std::views::drop(2); // ok
std::views::all(v) | std::views::drop(2); // also ok
}
Successfully compiled with g++11 -std=c++20
. But I cannot tell any difference between v | std::views::drop(2)
v | std::views::drop(2)
and std::views::all(v) | std::views::drop(2)
std::views::all(v) | std::views::drop(2)
.
So, my question is:
What is std::views::all
introduced for in C++20?
But I cannot tell any difference between
v | std::views::drop(2)
v | std::views::drop(2)
andstd::views::all(v) | std::views::drop(2)
std::views::all(v) | std::views::drop(2)
.
Indeed, there is no difference between the two - because v | views::drop(2)
v | views::drop(2)
already means views::all(v) | views::drop(2)
views::all(v) | views::drop(2)
.
views::all
is an implementation detail of Ranges to ensure that range adaptors always adapt views (not ranges). All that views::all(v)
does is ensure that the result is a View, which is to say (from [range.all] ):
Given a subexpression
E
, the expressionviews::all(E)
is expression-equivalent to:
decay-copy(E)
if the decayed type ofE
modelsview
.- Otherwise,
ref_view{E}
if that expression is well-formed.- Otherwise,
subrange{E}
.
In your case, v
is a vector<int>
, which does not model view
. But it is an lvalue, so ref_view{v}
would be well-formed, so that's what happens.
All the adaptors use views::all
internally. For instance, drop_view
has the following deduction guide:
template <class R>
drop_view(R&&, range_difference_t<R>) -> drop_view<views::all_t<R>>;
So if you wrote drop_view(v, 2)
(and you should never use meow_view
directly, always use views::meow
), that would itself invoke views::all
for you.
You may want your interface to return a range instead of the underlying container. In the example below, container_api
exposes member methods (ie of std::vector) that aren't part of a view (eg rbegin(), capacity(), max_size()). range_api
exposes operator bool
, which isn't part of a vector.
Another important difference is that the return type of range_api
is an object and not a reference. This may prevent unintentional copies from users thinking they are getting a range when the actual interface is returning a reference to a container.
class Foo {
public:
Foo() { ... }
const auto& container_api() const { return m_vec; }
auto range_api() const { return std::views::all(m_vec); }
private:
std::vector<int> m_vec;
};
void some_fn(const Foo& foo)
{
auto rng = foo.container_api(); // unwanted copy!
...
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.