std::ranges::to
|   在标头  <ranges> 定义
  | 
||
|   template< class C, ranges::input_range R, class... Args >   requires (!ranges::view<C>)  | 
(1) | (C++23 起) | 
|   template< template< class... > class C, ranges::input_range R, class... Args > constexpr auto to( R&& r, Args&&... args );  | 
(2) | (C++23 起) | 
|   template< class C, class... Args >   requires (!ranges::view<C>)  | 
(3) | (C++23 起) | 
|   template< template< class... > class C, class... Args > constexpr /*range adaptor closure*/ to( Args&&... args );  | 
(4) | (C++23 起) | 
|   辅助模板  | 
||
|   template< class Container > constexpr bool /*reservable-container*/ =  | 
(5) | (C++23 起) | 
|   template< class Container, class Reference > constexpr bool /*container-insertable*/ = requires (Container& c, Reference&& ref) {  | 
(6) | (C++23 起) | 
|   template< class Reference, class C > constexpr auto /*container-inserter*/( C& c ) {  | 
(7) | (C++23 起) | 
|   template< class R, class T > concept /*container-compatible-range*/ =  | 
(8) | (C++23 起) | 
范围转换函数的重载通过调用一个接受范围的构造函数、一个带有 std::from_range_t 标记的范围构造函数、一个接受迭代器-哨兵对的构造函数,或者通过将源范围的每个元素后插入到参数构造的对象中,来从第一个参数的源范围构造一个新的非视图对象。
r 的元素构造类型为 C 的对象:C 不满足 input_range 或者
std::convertible_to<ranges::range_reference_t<R>, ranges::range_value_t<C>> 为 true:C 的对象一样,如果以下所有条件都为 true:
- ranges::common_range<R>
 - 如果 std::iterator_traits<ranges::iterator_t<R>>::iterator_category 是有效的,并且表示满足 std::derived_fromstd::input_iterator_tag 的类型
 - std::constructible_from<C, ranges::iterator_t<R>, ranges::sentinel_t<R>, Args...>
 
C 的对象,并在构造后使用以下等效调用:
|   if constexpr (ranges::sized_range<R> && /*reservable-container*/<C>)   c.reserve(static_cast<ranges::range_size_t<C>>(ranges::size(r)));  | 
||
如果 R 满足 sized_range 并且 C 满足 /*reservable-container*/,则构造的类型为 C 的对象 c 能够以初始存储大小 ranges::size(r) 预留存储空间,以防止在插入新元素时进行额外的分配。r 的每个范围引用元素通过 ranges::copy 与尾部插入适配器一起尾部插入到 c 中。 上述操作在以下两个条件都为 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));  | 
||
如果 ranges::input_range<ranges::range_reference_t<C>> 为 true 则允许在范围内嵌套范围构造。
否则,程序非良构。r 的元素构造一个推导出的类型的对象。
使 /*input-iterator*/ 是一个仅用于阐述的类型,它满足 老式输入迭代器 (LegacyInputIterator) :
|   struct /*input-iterator*/ {                         // exposition only   using iterator_category = std::input_iterator_tag;  | 
||
定义 /*DEDUCE-EXPR*/ 为以下内容:
- C(std::declval<R>(), std::declval<Args>()...),如果该表达式是有效的。
 - 否则,C(std::from_range, std::declval<R>(), std::declval<Args>()...),如果该表达式是有效的。
 - 否则,C(std::declval</*input-iterator*/>(), std::declval</*input-iterator*/>(), std::declval<Args>()...),如果该表达式是有效的。
 - 否则,程序非良构。
 
该调用等效于
to<decltype(/*DEDUCE-EXPR*/)>(std::forward<R>(r), std::forward<Args>(args)...)。std::back_insert_iterator 的输出迭代器,如果成员函数 push_back 可用,否则类型为 std::insert_iterator。参数
| r | - | 源范围对象 | 
| args | - | 用于 (1-2) 构造一个范围或 (3-4) 绑定到范围适配器闭包对象的最后参数的参数列表。 | 
返回值
ranges::to return type
返回值从 ranges::range_adaptor_closure</*return-type*/> 继承。
成员对象
返回的对象的行为就像它没有目标对象一样,以及一个用 std::tuple<std::decay_t<Args>...>(std::forward<Args>(args)...) 构造的 std::tuple 对象 tup,除了返回的对象的赋值行为是未指定的,而且名字只是为了阐述。
构造函数
ranges::to (3-4) 的返回类型的行为就像它的复制/移动构造函数执行成员逐一复制/移动一样。如果它的所有成员对象(上面指定的)都是 可复制构造 (CopyConstructible)  的,那么它是可复制构造 (CopyConstructible)  的;否则,它是 可移动构造 (MoveConstructible)  的。
 成员函数 operator()
给定一个对象 G,它是从之前的调用 range::to</* see below */>(args...) 得到的,当一个指向 G 的 glvalue g 在函数调用表达式g(r) 中被调用时,会发生存储对象的调用,就像通过
- ranges::to</* see below */>(r, std::get<Ns>(g.tup)...),其中:
 
-  
r是一个必须满足input_range的源范围对象 -  
Ns是一个整数包0, 1, ..., (sizeof...(Args) - 1) -  
g在调用表达式中是一个左值,如果它在调用表达式中是一个左值,否则是一个右值。因此 std::move(g)(r) 可以将绑定的参数移动到调用中,而 g(r) 则会复制。 -  指定的模板参数是 (3) 
C或 (4) 从类模板C推导出的类型,它必须不满足view。 
-  
 
如果 g 具有 volatile 限定类型,则程序非良构。
异常
只抛出 range 对象构造时抛出的异常。
注解
向容器中插入元素可能涉及复制,这可能比移动更低效,因为在间接调用过程中会产生左值引用。用户可以选择使用 views::as_rvalue 来适配范围,以便它们的元素在间接调用过程中总是产生一个右值引用,这意味着移动。
| 功能特性测试宏 | 值 | 标准 | 备注 | 
|---|---|---|---|
__cpp_lib_ranges_to_container | 
202202L | (C++23) | std::ranges::to
 | 
示例
一个到 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 << ' '; }); }
输出:
2 4 6 8
参阅
- C++23 标准(ISO/IEC 14882:2023):
 
- 26.5.7 Range conversions [range.utility.conv]