std::ranges::move() 算法
- 自 C++20 起
- 简化
- 详细
// (1)
constexpr move_result<I, O>
move( I first, S last, O result );
// (2)
constexpr move_result<ranges::borrowed_iterator_t<R>, O>
move( R&& r, O result );
参数类型是泛型的,并具有以下约束:
I
-std::input_iterator
S
-std::sentinel_for<I>
O
-std::weakly_incrementable
- (2) -
R
-std::ranges::input_range
此外,每个重载都有以下约束
- (1) -
std::indirectly_movable<I, O>
- (2) -
std::indirectly_movable<ranges::iterator_t<R>, O>
// (1)
template<
std::input_iterator I,
std::sentinel_for<I> S,
std::weakly_incrementable O
>
requires std::indirectly_movable<I, O>
constexpr move_result<I, O>
move( I first, S last, O result );
// (2)
template<
ranges::input_range R,
std::weakly_incrementable O
>
requires std::indirectly_movable<ranges::iterator_t<R>, O>
constexpr move_result<ranges::borrowed_iterator_t<R>, O>
move( R&& r, O result );
辅助类型定义如下:
template< class I, class O >
using move_result = ranges::in_out_result<I, O>;
-
(1) 将由 [
first
;last
) 定义的范围内的元素移动到从result
开始的另一个范围。从其中移动的范围中的元素仍将包含适当类型的有效值,但不一定是移动之前相同的值。
未定义行为如果
result
在范围 [first
;last
) 内,则行为未定义。在这种情况下,可以改用ranges::move_backward
。 -
(2) 与 (1) 相同,但使用
r
作为源范围,如同使用ranges::begin(r)
作为first
和ranges::end(r)
作为last
。
本页描述的函数类实体是niebloids。
参数
first last | 要移动的元素范围。 |
r | 要移动的元素范围。 |
result | 目标范围的开头。 |
返回值
类型为 ranges::move_result
的值,初始化如下
{
last,
result + N
}
其中 N
是要从中移动元素的范围的大小。
复杂度
恰好 N
次移动赋值。
异常
(无)
可能的实现
move(1) 和 move(2)
struct move_fn
{
template<std::input_iterator I, std::sentinel_for<I> S, std::weakly_incrementable O>
requires std::indirectly_movable<I, O>
constexpr ranges::move_result<I, O>
operator()(I first, S last, O result) const
{
for (; first != last; ++first, ++result)
*result = ranges::iter_move(first);
return {std::move(first), std::move(result)};
}
template<ranges::input_range R, std::weakly_incrementable O>
requires std::indirectly_movable<ranges::iterator_t<R>, O>
constexpr ranges::move_result<ranges::borrowed_iterator_t<R>, O>
operator()(R&& r, O result) const
{
return (*this)(ranges::begin(r), ranges::end(r), std::move(result));
}
};
inline constexpr move_fn move {};
备注
在移动重叠范围时,ranges::move
适用于向左移动(目标范围的开头在源范围之外),
而 ranges::move_backward
适用于向右移动(目标范围的结尾在源范围之外)。
示例
以下代码将线程对象(它们本身不可复制)从一个容器移动到另一个容器。
#include <algorithm>
#include <chrono>
#include <iostream>
#include <iterator>
#include <list>
#include <thread>
#include <vector>
using namespace std::literals::chrono_literals;
void f(std::chrono::milliseconds n)
{
std::this_thread::sleep_for(n);
std::cout << "thread with n=" << n.count() << "ms ended" << std::endl;
}
int main()
{
std::vector<std::jthread> v;
v.emplace_back(f, 400ms);
v.emplace_back(f, 600ms);
v.emplace_back(f, 800ms);
std::list<std::jthread> l;
// std::ranges::copy() would not compile, because std::jthread is non-copyable
std::ranges::move(v, std::back_inserter(l));
}
thread with n=400ms ended
thread with n=600ms ended
thread with n=800ms ended