std::ranges::to
Defined in header <ranges>
|
||
template< class C, ranges::input_range R, class... Args > requires (!ranges::view<C>) |
(1) | (since C++23) |
template< template< class... > class C, ranges::input_range R, class... Args > constexpr auto to( R&& r, Args&&... args ); |
(2) | (since C++23) |
template< class C, class... Args > requires (!ranges::view<C>) |
(3) | (since C++23) |
template< template< class... > class C, class... Args > constexpr /*range adaptor closure*/ to( Args&&... args ); |
(4) | (since C++23) |
Helper templates |
||
template< class Container > constexpr bool /*reservable-container*/ = |
(5) | (since C++23) |
template< class Container, class Reference > constexpr bool /*container-insertable*/ = requires (Container& c, Reference&& ref) { |
(6) | (since C++23) |
template< class Reference, class C > constexpr auto /*container-inserter*/( C& c ) { |
(7) | (since C++23) |
template< class R, class T > concept /*container-compatible-range*/ = |
(8) | (since C++23) |
The overloads of the range conversion function construct a new non-view object from a source range as its first argument by calling a constructor taking a range, a std::from_range_t
tagged ranged constructor, a constructor taking an iterator-sentinel pair, or by back inserting each element of the source range into the arguments-constructed object.
C
from the elements of r
in the following:C
does not satisfy input_range
or std::convertible_to<ranges::range_reference_t<R>, ranges::range_value_t<C>> is true:C
from the source range std::forward<R>(r) and the rest of the functional arguments std::forward<Args>(args)... if std::constructible_from<C, R, Args...> is true.C
from additional disambiguation tag std::from_range, the source range std::forward<R>(r) and the rest of the functional arguments std::forward<Args>(args)... if std::constructible_from<C, std::from_range_t, R, Args...> is true.C
from the iterator-sentinel pair (ranges::begin(r) as an iterator and ranges::end(r) as sentinel, where iterator and sentinel have the same type. In other words, the source range must be a common range), and the rest of function arguments std::forward<Args>(args)... if all of the conditions below are true:
- ranges::common_range<R>
- If std::iterator_traits<ranges::iterator_t<R>>::iterator_category is valid and denotes a type that satisfies std::derived_from<std::input_iterator_tag>
- std::constructible_from<C, ranges::iterator_t<R>, ranges::sentinel_t<R>, Args...>
C
from the rest of the function arguments std::forward<Args>(args)... with the following equivalent call below after the construction:
if constexpr (ranges::sized_range<R> && /*reservable-container*/<C>) c.reserve(static_cast<ranges::range_size_t<C>>(ranges::size(r))); |
||
If the R
satisfies sized_range
and C
satisfies /*reservable-container*/, the constructed object c
of type C
is able to reserve storage with the initial storage size ranges::size(r) to prevent additional allocations during inserting new elements. Each range reference element of r
is back inserted to c
through ranges::copy
with back inserter adaptor.
The operations above are valid if both of the conditions below are true:
- std::constructible_from<C, Args...>
- /*container-insertable*/<C, ranges::range_reference_t<R>>
to<C>(r | views::transform([](auto&& elem) { return to<ranges::range_value_t<C>>(std::forward<decltype(elem)>(elem)); |
||
Which allows nested range constructions within the range if ranges::input_range<ranges::range_reference_t<C>> is true.
Otherwise, the program is ill-formed.r
.
Let /*input-iterator*/ be an exposition only type that satisfies LegacyInputIterator:
struct /*input-iterator*/ { // exposition only using iterator_category = std::input_iterator_tag; |
||
Let /*DEDUCE-EXPR*/ be defined as follows:
- C(std::declval<R>(), std::declval<Args>()...), if that expression is valid.
- Otherwise, C(std::from_range, std::declval<R>(), std::declval<Args>()...), if that expression is valid.
- Otherwise, C(std::declval</*input-iterator*/>(), std::declval</*input-iterator*/>(), std::declval<Args>()...), if that expression is valid.
- Otherwise, the program is ill-formed.
std::back_insert_iterator
if member function push_back is available, otherwise the type is std::insert_iterator
.Contents |
[edit] Parameters
r | - | a source range object |
args | - | list of the arguments to (1-2) construct a range or (3-4) bind to the last parameters of range adaptor closure object. |
[edit] Return value
ranges::to return type
The return type is derived from ranges::range_adaptor_closure</*return-type*/>.
Member objects
The returned object behaves as if it has no target object, and an std::tuple object tup
constructed with std::tuple<std::decay_t<Args>...>(std::forward<Args>(args)...), except that the returned object's assignment behavior is unspecified and the names are for exposition only.
Constructors
The return type of ranges::to
(3-4) behaves as if its copy/move constructors perform a memberwise copy/move. It is CopyConstructible if all of its member objects (specified above) are CopyConstructible, and is MoveConstructible otherwise.
Member function operator()
Given an object G
obtained from an earlier call to range::to</* see below */>(args...), when a glvalue g
designating G
is invoked in a function call expression g(r), an invocation of the stored object takes place, as if by
- ranges::to</* see below */>(r, std::get<Ns>(g.tup)...), where
-
r
is a source range object that must satisfyinput_range
-
Ns
is an integer pack0, 1, ..., (sizeof...(Args) - 1)
-
g
is an lvalue in the call expression if it is an lvalue in the call expression, and is an rvalue otherwise. Thus std::move(g)(r) can move the bound arguments into the call, where g(r) would copy. - The specified template argument is (3)
C
or (4) the deduced type from a class templateC
that must not satisfyview
.
-
The program is ill-formed if g
has volatile-qualified type.
[edit] Exceptions
Only throws if construction of a range object throws.
[edit] Notes
The insertion of elements into the container may involve copy which can be more inefficient than move because lvalue references are produced during the indirection call. Users can opt-in to use views::as_rvalue to adapt the range in order for their elements to always produce an rvalue reference during the indirection call which implies move.
Feature-test macro | Value | Std | Comment |
---|---|---|---|
__cpp_lib_ranges_to_container |
202202L | (C++23) | std::ranges::to
|
[edit] Example
A link to test Compiler Explorer msvc.latest
#include <algorithm> #include <concepts> #include <iostream> #include <ranges> #include <vector> int main() { auto vec = std::views::iota(1, 5) | std::views::transform([](auto const v){ return v * 2; }) | std::ranges::to<std::vector>(); static_assert(std::same_as<decltype(vec), std::vector<int>>); std::ranges::for_each(vec, [](auto const v){ std::cout << v << ' '; }); }
Output:
2 4 6 8
[edit] References
- C++23 standard (ISO/IEC 14882:2023):
- 26.5.7 Range conversions [range.utility.conv]