std::ranges::advance
来自cppreference.com
<tbody>
</tbody>
| 在标头 <iterator> 定义
|
||
| 调用签名 |
||
template< std::input_or_output_iterator I > constexpr void advance( I& i, std::iter_difference_t<I> n ); |
(1) | (C++20 起) |
template< std::input_or_output_iterator I, std::sentinel_for<I> S > constexpr void advance( I& i, S bound ); |
(2) | (C++20 起) |
template< std::input_or_output_iterator I, std::sentinel_for<I> S > constexpr std::iter_difference_t<I> advance( I& i, std::iter_difference_t<I> n, S bound ); |
(3) | (C++20 起) |
1) 自增给定的迭代器
i n 次。2) 自增给定的迭代器
i 直至 i == bound。3) 自增给定的迭代器
i n 次,或直至 i == bound,取决于何者先达成。若 n 为负数,则自减迭代器。此情况下,I 必须实现 std::bidirectional_iterator,而若提供了 bound 则 S 必须与 I 为同一类型,否则行为未定义。
此页面上描述的函数式实体是算法函数对象(非正式地称为 niebloid),即:
参数
| i | - | 要推进的迭代器 |
| bound | - | 哨位,代表 i 作为迭代器所指向的范围的结尾
|
| n | - | i 应自增的次数
|
返回值
3)
n 与 i 所遍历的实际距离之间的差。复杂度
线性。
然而,若 I 额外实现 std::random_access_iterator,或若 S 实现 std::sized_sentinel_for<I>,或若 I 与 S 实现 std::assignable_from<I&, S>,则复杂度为常数。
注解
若指定的自增或自减序列会要求自增不可自增的迭代器(例如尾后迭代器),或自减不可自减的迭代器(例如首迭代器或孤立迭代器),则行为未定义。
可能的实现
struct advance_fn
{
template<std::input_or_output_iterator I>
constexpr void operator()(I& i, std::iter_difference_t<I> n) const
{
if constexpr (std::random_access_iterator<I>)
i += n;
else
{
while (n > 0)
{
--n;
++i;
}
if constexpr (std::bidirectional_iterator<I>)
{
while (n < 0)
{
++n;
--i;
}
}
}
}
template<std::input_or_output_iterator I, std::sentinel_for<I> S>
constexpr void operator()(I& i, S bound) const
{
if constexpr (std::assignable_from<I&, S>)
i = std::move(bound);
else if constexpr (std::sized_sentinel_for<S, I>)
(*this)(i, bound - i);
else
while (i != bound)
++i;
}
template<std::input_or_output_iterator I, std::sentinel_for<I> S>
constexpr std::iter_difference_t<I>
operator()(I& i, std::iter_difference_t<I> n, S bound) const
{
if constexpr (std::sized_sentinel_for<S, I>)
{
// std::abs 在 C++23 前非 constexpr
auto abs = [](const std::iter_difference_t<I> x) { return x < 0 ? -x : x; };
if (const auto dist = abs(n) - abs(bound - i); dist < 0)
{
(*this)(i, bound);
return -dist;
}
(*this)(i, n);
return 0;
}
else
{
while (n > 0 && i != bound)
{
--n;
++i;
}
if constexpr (std::bidirectional_iterator<I>)
{
while (n < 0 && i != bound)
{
++n;
--i;
}
}
return n;
}
}
};
inline constexpr auto advance = advance_fn();
|
示例
运行此代码
#include <iostream>
#include <iterator>
#include <vector>
int main()
{
std::vector<int> v {3, 1, 4};
auto vi = v.begin();
std::ranges::advance(vi, 2);
std::cout << "1) value: " << *vi << '\n' << std::boolalpha;
std::ranges::advance(vi, v.end());
std::cout << "2) vi == v.end(): " << (vi == v.end()) << '\n';
std::ranges::advance(vi, -3);
std::cout << "3) value: " << *vi << '\n';
std::cout << "4) diff: " << std::ranges::advance(vi, 2, v.end())
<< ", value: " << *vi << '\n';
std::cout << "5) diff: " << std::ranges::advance(vi, 4, v.end())
<< ", vi == v.end(): " << (vi == v.end()) << '\n';
}
输出:
1) value: 4
2) vi == v.end(): true
3) value: 3
4) diff: 0, value: 4
5) diff: 3, vi == v.end(): true
参阅
(C++20) |
自增迭代器给定的距离或到边界 (算法函数对象) |
(C++20) |
自减迭代器给定的距离或到边界 (算法函数对象) |
(C++20) |
返回迭代器与哨位间的距离,或范围起始与结尾间的距离 (算法函数对象) |
| 令迭代器前进给定的距离 (函数模板) |