owning_view
class (C++ Standard Library)
A view that takes ownership of the elements in another range.
Syntax
template<range R>
requires std::movable<R> && (!is-initializer-list<R>)
class owning_view : public ranges::view_interface<owning_view<R>>;
Template parameters
R
The type of the underlying range.
View characteristics
For a description of the following entries, see View class characteristics
Characteristic | Description |
---|---|
Range adaptor | views::all |
Underlying range | Must satisfy input_range or higher |
Element type | Same as the underlying range |
View iterator category | Same as the underlying range |
Sized | Only if the underlying range satisfies sized_range |
Is const -iterable |
Only if the underlying range satisfies const-iterable |
Common range | Only if the underlying range satisfies common_range |
Borrowed range | Only if the underlying range satisfies borrowed_range |
Members
Member functions | Description |
---|---|
Constructors | Construct an owning_view . |
base C++20 |
Get a reference to the owned range. |
begin C++20 |
Get an iterator to the first element. |
data C++20 |
Get a pointer to the first element. |
empty C++20 |
Test whether the view is empty. |
end C++20 |
Get the sentinel at the end of the view. |
size C++20 |
Get the number of elements. |
operator= |
Assign (move) the contents from another owning_view to this one. |
Inherited from view_interface |
Description |
back C++20 |
Get the last element. |
front C++20 |
Get the first element. |
operator[] C++20 |
Get the element at the specified position. |
operator bool C++20 |
Test whether the view isn't empty. |
Remarks
The best way to create an owning_view
is by using the views::all
range adaptor. Range adaptors are the intended way to create view classes. The view types are exposed in case you want to create your own custom view type.
Even though this class owns its elements, it's not expensive to construct because the underlying range is moved using std::move()
.
This view is useful when you want a range that doesn't depend on the lifetime of the container providing the elements.
Requirements
Header: <ranges>
(since C++20)
Namespace: std::ranges
Compiler Option: /std:c++20
or later is required.
Constructors
Create an instance of a owning_view
.
1) owning_view() requires default_initializable<R> = default;
2) constexpr owning_view(R&& rg);
3) owning_view(const owning_view& v) = delete; // no copy constructor
4) owning_view(const owning_view&& v) = default; // move constructor
Parameters
rg
The range to move to the owning_view
.
v
The owning_view
to move to the new owning_view
.
For information about template parameter types, see Template parameters.
Remarks
1) The default constructor creates a default-initialized owning_view
.
2) Move constructs the owning_view
from rg
.
3) An owning_view
can't be copied, only moved.
4) Construct the owning_view
from another owning_view
.
Example: owning_view
// requires /std:c++20 or later
#include <ranges>
#include <iostream>
#include <vector>
#include <utility>
int main()
{
std::vector<int> v = {1,2,3,4,5,6,7,8,9,10};
auto myOwningView = std::views::all(std::move(v)); // create an owning_view from a moved vector
std::cout << v.size() << '\n'; // outputs 0 because myOwningView now owns the elements
std::cout << myOwningView.size() << '\n'; // outputs 10
std::vector<int> v2 = {1,2,3,4,5};
std::ranges::owning_view<std::vector<int>> ov2{std::move(v2)};
std::cout << v2.size() << '\n'; // outputs 0 because ov2 now owns the elements
std::cout << ov2.size() << '\n'; // outputs 5
}
0
10
0
5
base
Gets a reference to the underlying range.
1) constexpr R& base() & noexcept { return r_; }
2) constexpr const R& base() const & noexcept { return r_; }
3) constexpr R&& base() && noexcept { return std::move(r_); }
4) constexpr const R&& base() const && noexcept { return std::move(r_); }
Parameters
None.
Return value
A reference to the underlying range, call it rg
.
For 1 & 2, the underlying range is returned via return rg;
For 3 & 4, the underlying range is returned via std::move(rg);
begin
Get an iterator to the first element in the view.
constexpr iterator_t<R> begin();
constexpr auto begin() const requires range<const R>;
Parameters
None.
Return value
An iterator pointing at the first element in the view:
data
Get a pointer to the first element in the view.
constexpr auto data()
requires std::contiguous_iterator<ranges::iterator_t<R>>;
constexpr auto data() const
requires std::contiguous_iterator<ranges::iterator_t<const R>>;
Parameters
None.
Return value
A pointer to the first element in the view.
Remarks
The underlying owned range must satisfy contiguous_range
.
empty
Test whether the view is empty.
constexpr bool empty();
constexpr bool empty() const;
Parameters
None.
Return value
Returns true
if the underlying range has no elements. Otherwise, returns false
.
end
Get the sentinel at the end of the view.
constexpr sentinel_t<R> end();
constexpr auto end() const requires range<const R>
Return value
The sentinel that follows the last element in the view:
size
Get the number of elements in the view.
constexpr auto size() requires ranges::sized_range<R>;
constexpr auto size() const requires ranges::sized_range<const R>;
Parameters
None.
Return value
The number of elements in the view.
operator=
Assign (move) the contents from another owning_view
to this one.
owning_view& operator=(owning_view&&) = default;
Parameters
The owning_view
to assign (move) to this one.
Return value
*this
Remarks
An owning_view
can't be copied, only moved.
Example: operator=
// requires /std:c++20 or later
#include <ranges>
#include <iostream>
#include <vector>
int main()
{
std::vector<int> v1 = {1,2,3};
std::ranges::owning_view<std::vector<int>> ov1{std::move(v1)};
std::vector<int> v2 = {4,5,6};
std::ranges::owning_view<std::vector<int>> ov2{std::move(v2)};
// operator=
ov2 = std::move(ov1);
// ov1 took ownership of v1, so v1 is empty
// ov2 took ownership of v2, so v2 is empty
// ov2 then took ownership of ov1, so ov1 is empty
// ov2 now owns the elements 1, 2, 3
std::cout << std::boolalpha << "v1.empty():" << v1.empty() << " ov1.empty():" << ov1.empty() << '\n'; // v1.empty():true ov1.empty():true
std::cout << "v2.empty():" << v2.empty() << " ov2.size():" << ov2.size() << '\n'; // v2.empty():true ov2.size():3
for (auto e : ov2)
{
std::cout << e << ' '; // 1 2 3
}
}
v1.empty():true ov1.empty():true
v2.empty():true ov2.size():3
1 2 3