std::ranges::uninitialized_move_n, std::ranges::uninitialized_move_n_result
| ヘッダ <memory> で定義 |
||
| 呼び出しシグネチャ |
||
template< std::input_iterator I, no-throw-forward-iterator O, no-throw-sentinel-for<O> S > |
(1) | (C++20以降) (C++26 以降 constexpr) |
| ヘルパー型 |
||
| template< class I, class O > using uninitialized_move_n_result = ranges::in_out_result<I, O>; |
(2) | (C++20以降) |
Let N be ranges::min(count, ranges::distance(ofirst, olast)).
Copies N elements from the range beginning at ifirst (using move semantics if supported) to an uninitialized memory area [ofirst, olast) as if by auto ret = ranges::uninitialized_move(std::counted_iterator(std::move(ifirst), count),
std::default_sentinel, ofirst, olast);
return {std::move(ret.in).base(), ret.out};
If an exception is thrown during the initialization then the objects that already constructed in [ofirst, olast) are destroyed in an unspecified order. Also, the objects in the input range beginning at ifirst, that were already moved, are left in a valid but unspecified state.
If [ofirst, olast) overlaps with ifirst + [0, count), the behavior is undefined.
このページで説明されている関数のようなエンティティは、アルゴリズム関数オブジェクト(非公式にはニーブロイドとして知られている)です。つまり、
- これらのいずれかを呼び出す際に、明示的なテンプレート引数リストを指定することはできません。
- これらのいずれも実引数依存の名前探索には見えません。
- これらのいずれかが関数呼び出し演算子の左側の名前として通常の非修飾名探索によって見つかった場合、実引数依存の名前探索は抑制されます。
目次 |
[編集] パラメータ
| ifirst | - | 移動元の入力範囲の開始イテレータ |
| ofirst, olast | - | 初期化する出力範囲を定義するイテレータとセンチネルのペア |
| n | - | 移動する要素数 |
[編集] 戻り値
上記の通り。
[編集] 計算量
𝓞(N)。
[編集] 例外
変換先範囲の要素の構築時にスローされる例外。
[編集] 注意
実装によっては、出力範囲の値型がTrivialTypeである場合、ranges::copy_nを使用してranges::uninitialized_move_nの効率を向上させることができます。
| 機能テストマクロ | 値 | 規格 | 機能 |
|---|---|---|---|
__cpp_lib_raw_memory_algorithms |
202411L |
(C++26) | 特殊なメモリアルゴリズムの場合、(1) は constexpr です。 |
[編集] 考えられる実装
struct uninitialized_move_n_fn { template<std::input_iterator I, no-throw-forward-iterator O, no-throw-sentinel-for<O> S> requires std::constructible_from<std::iter_value_t<O>, std::iter_rvalue_reference_t<I>> constexpr ranges::uninitialized_move_n_result<I, O> operator()(I ifirst, std::iter_difference_t<I> count, O ofirst, S olast) const { auto iter = std::counted_iterator(std::move(ifirst), count); auto ret = ranges::uninitialized_move(iter, std::default_sentinel, ofirst, olast); return {std::move(ret.in).base(), ret.out}; } }; inline constexpr uninitialized_move_n_fn uninitialized_move_n{}; |
[編集] 例
#include <cstdlib> #include <iomanip> #include <iostream> #include <memory> #include <string> void print(auto rem, auto first, auto last) { for (std::cout << rem; first != last; ++first) std::cout << std::quoted(*first) << ' '; std::cout << '\n'; } int main() { std::string in[]{ "No", "Diagnostic", "Required", }; print("initially, in: ", std::begin(in), std::end(in)); if ( constexpr auto sz = std::size(in); void* out = std::aligned_alloc(alignof(std::string), sizeof(std::string) * sz) ) { try { auto first{static_cast<std::string*>(out)}; auto last{first + sz}; std::ranges::uninitialized_move_n(std::begin(in), sz, first, last); print("after move, in: ", std::begin(in), std::end(in)); print("after move, out: ", first, last); std::ranges::destroy(first, last); } catch (...) { std::cout << "Exception!\n"; } std::free(out); } }
実行結果の例
initially, in: "No" "Diagnostic" "Required" after move, in: "" "" "" after move, out: "No" "Diagnostic" "Required"
[編集] 不具合報告
以下の動作変更を伴う欠陥報告が、以前に公開されたC++標準に遡って適用されました。
| DR | 適用対象 | 公開された動作 | 正しい動作 |
|---|---|---|---|
| LWG 3870 | C++20 | このアルゴリズムは、const ストレージ上にオブジェクトを作成する可能性があります。 | 禁止されたままです。 |
[編集] 関連項目
| (C++20) |
オブジェクトの範囲を未初期化メモリ領域にムーブします (アルゴリズム関数オブジェクト) |
| (C++17) |
指定された数のオブジェクトを未初期化メモリ領域にムーブします (関数テンプレート) |