std::ranges::size
在头文件 <ranges> 中定义 |
||
在头文件 <iterator> 中定义 |
||
inline namespace /* 未指定 */ { inline constexpr auto size = /* 未指定 */; |
(自 C++20 起) (定制点对象) |
|
调用签名 |
||
template< class T > requires /* 见下文 */ |
(自 C++20 起) | |
以常数时间计算 t 中的元素数量。
给定 t 表示的(可能已 具体化)结果对象的子表达式为 E,E 的类型为 T
- 如果
T
是一个未知边界的数组,则 ranges::size(E) 将是非法的。 - 否则,如果
T
是一个数组类型,则 ranges::size(E) 将与 decay-copy (std::extent_v<T>)(直到 C++23)auto(std::extent_v<T>)(自 C++23 起) 等效。 - 否则,如果满足以下所有条件,则 ranges::size(E) 将与 decay-copy (t.size())(直到 C++23)auto(t.size())(自 C++23 起) 等效
- ranges::disable_sized_range<std::remove_cv_t<T>> 为 false。
- decay-copy (t.size())(直到 C++23)auto(t.size())(自 C++23 起) 是一个有效的 整数类型 表达式。
- 否则,如果满足以下所有条件,则 ranges::size(E) 将与 decay-copy (size(t))(直到 C++23)auto(size(t))(自 C++23 起) 等效
-
T
是一个类或枚举类型。 - ranges::disable_sized_range<std::remove_cv_t<T>> 为 false。
- decay-copy (size(t))(直到 C++23)auto(size(t))(自 C++23 起) 是一个有效的整数类型表达式,其中
size
的含义是通过仅执行 参数相关查找 来确定的。
-
- 否则,如果满足以下所有条件,则 ranges::size(E) 将与
to-unsigned-like
(ranges::end(t) - ranges::begin(t)) 等效-
T
模型forward_range
。 - 给定 ranges::begin(t) 的类型为
I
,ranges::end(t) 的类型为S
,sized_sentinel_for
<S, I> 和forward_iterator
<I> 都将被建模。 -
to-unsigned-like
(ranges::end(t) - ranges::begin(t)) 是一个有效的表达式。
-
- 否则,ranges::size(E) 是非法的。
上述可诊断的非法情况会导致 替换失败,当 ranges::size(E) 出现在模板实例化的直接上下文中时。
内容 |
定制点对象
名称 ranges::size
表示一个定制点对象,它是一个 const 函数对象,其类型为 字面量 semiregular
类类型。为了说明目的,其类型的 cv 无限定版本表示为 __size_fn
。
所有 __size_fn
的实例都是相等的。调用类型为 __size_fn
的不同实例对相同参数的效果相同,无论表示该实例的表达式是左值还是右值,以及是否具有 const 限定符(但是,volatile 限定符的实例不需要可调用)。因此,ranges::size
可以自由复制,并且其副本可以互换使用。
给定一组类型 Args...
,如果 std::declval<Args>()... 满足上述 ranges::size
参数的要求,则 __size_fn
模拟
- std::invocable<__size_fn, Args...>,
- std::invocable<const __size_fn, Args...>,
- std::invocable<__size_fn&, Args...>,以及
- std::invocable<const __size_fn&, Args...>.
否则,__size_fn
的任何函数调用运算符都不会参与重载解析。
[edit] 注意
每当对于表达式 e,ranges::size(e) 有效时,返回值类型为 整数类型。
C++20 标准要求,如果底层的 size
函数调用返回右值,则返回值将从生成的临时对象中移动构造。所有实现都直接返回右值。该要求由 C++20 后的提案 P0849R8 更正以匹配实现。
表达式 ranges::distance(e) 也可用于确定范围 e 的大小。与 ranges::size(e) 不同,ranges::distance(e) 即使 e 是一个无大小范围,也能正常工作,代价是这种情况下的复杂度为线性。
[edit] 示例
#include <iostream> #include <ranges> #include <type_traits> #include <vector> int main() { auto v = std::vector<int>{}; std::cout << "ranges::size(v) == " << std::ranges::size(v) << '\n'; auto il = {7}; // std::initializer_list std::cout << "ranges::size(il) == " << std::ranges::size(il) << '\n'; int array[]{4, 5}; // array has a known bound std::cout << "ranges::size(array) == " << std::ranges::size(array) << '\n'; static_assert(std::is_signed_v<decltype(std::ranges::size(v))> == false); }
输出
ranges::size(v) == 0 ranges::size(il) == 1 ranges::size(array) == 2
[edit] 缺陷报告
以下行为更改的缺陷报告被追溯地应用于以前发布的 C++ 标准。
DR | 应用于 | 已发布的行为 | 正确行为 |
---|---|---|---|
P2602R2 | C++20 | 存在机制来禁止通过 ADL 找到的某些非成员 size |
删除了此类机制 |
[edit] 参见
(C++20) |
返回一个有符号整数,该整数等于范围的大小 (定制点对象) |
(C++20) |
指定范围以恒定时间了解其大小 (概念) |
(C++20) |
返回迭代器和哨兵之间的距离,或者返回范围的起点和终点之间的距离 (类模板) |
(C++17)(C++20) |
返回容器或数组的大小 (函数模板) |