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
>
|
(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) | ( 仅用于说明* ) |
|
template
<
class
Container,
class
Reference
>
constexpr
bool
/*container-appendable*/
=
|
(6) | ( 仅用于说明* ) |
|
template
<
class
Reference,
class
C
>
constexpr auto /*container-appender*/ ( C & c ) ; |
(7) | ( 仅用于说明* ) |
|
template
<
class
R,
class
T
>
concept
/*container-compatible-range*/
=
|
(8) | ( 仅用于说明* ) |
范围转换函数的重载通过以下方式从作为首个参数的源范围构造新的非视图对象:调用接受范围的构造函数、调用带
std::from_range_t
标签的范围构造函数、调用接受迭代器-哨位对的构造函数,或者通过将源范围的每个元素后插入到由参数构造的对象中。
C
的对象:
C
不满足
input_range
或
std::
convertible_to
<
ranges::
range_reference_t
<
R
>
,
ranges::
range_value_t
<
C
>>
为
true
:
C
的对象进行
直接初始化
(但不包括直接列表初始化)的方式构造非视图对象,前提是
std::
constructible_from
<
C,
std::
from_range_t
, R, Args...
>
为
true
。
C
的对象那样构造非视图对象,当以下所有条件均为
true
时:
- ranges:: common_range < R >
- 若 std:: iterator_traits < ranges:: iterator_t < R >> :: iterator_category 有效且表示满足 std:: derived_from < std:: 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++26 前) |
|
if
constexpr
(
ranges
::
approximately_sized_range
<
R
>
|
(C++26 起) |
若
R
满足
sized_range
(C++26 前)
approximately_sized_range
(C++26 起)
且
C
满足
reservable-container
,则类型
C
的构造对象
c
能够以初始存储大小
ranges::
size
(
r
)
(C++26 前)
ranges
::
reserve_hint
(
r
)
(C++26 起)
预留存储空间,以避免在插入新元素时进行额外分配。
r
的每个元素会被追加到
c
中。
当以下两个条件均为 true 时,上述操作有效:
- std:: constructible_from < C, Args... >
-
container-appendable< C, ranges:: range_reference_t < R >>
to
<
C
>
(
ranges::
ref_view
(
r
)
|
views::
transform
(
[
]
(
auto
&&
elem
)
{
return
to
<
ranges::
range_value_t
<
C
>>
(
std::
forward
<
decltype
(
elem
)
>
(
elem
)
)
;
}
)
,
std::
forward
<
Args
>
(
args
)
...
)
这允许在范围内部进行嵌套范围构造,当
ranges::
input_range
<
ranges::
range_reference_t
<
C
>>
为
true
时。
令 /*input-iterator*/ 为满足 LegacyInputIterator 的说明专用类型:
|
struct
/*input-iterator*/
{
|
( 说明专用* ) | |
令 /*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 > ( ) ... ) ,若该表达式合法。 - 否则,程序非良构。
( std:: forward < R > ( r ) , std:: forward < Args > ( args ) ... ) 。
emplace_back
、
push_back
、
emplace
或
insert
将
Reference
类型的元素追加到
Container
中。
return
[
&
c
]
<
class
Reference
>
(
Reference
&&
ref
)
{
if
constexpr
(
requires
{
c.
emplace_back
(
std::
declval
<
Reference
>
(
)
)
;
}
)
c.
emplace_back
(
std::
forward
<
Reference
>
(
ref
)
)
;
else
if
constexpr
(
requires
{
c.
push_back
(
std::
declval
<
Reference
>
(
)
)
;
}
)
c.
push_back
(
std::
forward
<
Reference
>
(
ref
)
)
;
else
if
constexpr
(
requires
{
c.
emplace
(
c.
end
(
)
,
std::
declval
<
Reference
>
(
)
)
;
}
)
c.
emplace
(
c.
end
(
)
,
std::
forward
<
Reference
>
(
ref
)
)
;
else
c.
insert
(
c.
end
(
)
,
std::
forward
<
Reference
>
(
ref
)
)
;
}
;
R
,其范围引用类型必须可转换为
T
。
目录 |
参数
| r | - | 源范围对象 |
| args | - | 用于 ( 1,2 ) 构造范围的参数列表,或 ( 3,4 ) 绑定到范围适配器闭包对象最后参数的参数列表 |
| 类型要求 | ||
-
C
必须是 cv-未限定的类类型
(
1,3
)
|
||
返回值
ranges::to 返回类型
成员对象
返回的对象表现为没有目标对象,并具有一个用 tup 构造的 std::tuple 对象 std:: tuple < std:: decay_t < Args > ... > ( std:: forward < Args > ( args ) ... ) ,但返回对象的赋值行为未指定且名称仅用于说明目的。
构造函数
ranges::to
(
3,4
)
的返回类型表现为其拷贝/移动构造函数执行成员级的拷贝/移动。如果其所有成员对象(如上所述)均满足
可拷贝构造
,则该类型为
可拷贝构造
,否则为
可移动构造
。
成员函数
operator()
给定从先前调用
range
::
to
<
/* see below */
>
(
args...
)
获得的对象
G
,当指代
G
的泛左值
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。
-
r
是必须满足
如果 g 具有 volatile 限定类型,则程序非良构。
异常
仅当非视图对象的构造抛出异常时才会抛出。
注释
向容器中插入元素可能涉及拷贝操作,由于间接调用过程中会产生左值引用,这比移动操作的效率更低。用户可以选择使用 views:: as_rvalue 来适配范围,使得其元素在间接调用过程中始终产生右值引用,这意味着将执行移动操作。
使用管道语法时圆括号是必需的。
auto vec = r | std::ranges::to<std::vector>; // 错误 auto vec = r | std::ranges::to<std::vector>(); // 正确
| 功能测试 宏 | 值 | 标准 | 功能特性 |
|---|---|---|---|
__cpp_lib_ranges_to_container
|
202202L
|
(C++23) |
std::ranges::to
|
__cpp_lib_ranges_reserve_hint
|
202502L
|
(C++26) |
ranges::approximately_sized_range
,
ranges::reserve_hint
及对
std::ranges::to
的
变更
|
示例
预览链接: Compiler Explorer
#include <boost/container/devector.hpp> #include <concepts> #include <initializer_list> #include <list> #include <print> #include <ranges> #include <regex> #include <string> #include <vector> #ifndef __cpp_lib_format_ranges #include <format> #include <sstream> auto print_aid(const auto& v) { std::ostringstream out; out << '['; for (int n{}; const auto& e : v) out << (n++ ? ", " : "") << e; out << ']'; return out; } template<typename T> struct std::formatter<std::vector<T>, char> { template<class ParseContext> constexpr ParseContext::iterator parse(ParseContext& ctx) { return ctx.begin(); } template<class FmtContext> FmtContext::iterator format(auto const& s, FmtContext& ctx) const { auto out{print_aid(s)}; return std::ranges::copy(std::move(out).str(), ctx.out()).out; } }; template<typename T> struct std::formatter<std::list<T>, char> { template<class ParseContext> constexpr ParseContext::iterator parse(ParseContext& ctx) { return ctx.begin(); } template<class FmtContext> FmtContext::iterator format(auto const& s, FmtContext& ctx) const { auto out{print_aid(s)}; return std::ranges::copy(std::move(out).str(), ctx.out()).out; } }; #endif int main() { auto vec = std::views::iota(1, 5) | std::views::transform([](int v){ return v * 2; }) | std::ranges::to<std::vector>(); static_assert(std::same_as<decltype(vec), std::vector<int>>); std::println("{}", vec); auto list = vec | std::views::take(3) | std::ranges::to<std::list<double>>(); std::println("{}", list); } void ctor_demos() { // 1.a.1) 直接初始化 { char array[]{'a', 'b', '\0', 'c'}; // 参数类型可转换为结果值类型: auto str_to = std::ranges::to<std::string>(array); // 等价于 std::string str(array); // 结果类型不是输入范围: auto re_to = std::ranges::to<std::regex>(array)<span class="
缺陷报告
下列行为变更缺陷报告被追溯应用于先前发布的 C++ 标准。
| DR | 适用范围 | 发布时的行为 | 修正后的行为 |
|---|---|---|---|
| LWG 3984 | C++23 |
当
R&
不满足
viewable_range
概念时,
ranges::to
的嵌套构造分支会导致程序非良构
|
改为良构 |
| LWG 4016 | C++23 |
ranges::to
的容器插入分支
使用了插入迭代器 |
改为直接向容器
追加元素 |
参考文献
- C++23 标准 (ISO/IEC 14882:2024):
-
- 26.5.7 范围转换 [range.utility.conv]