std::ranges::uninitialized_move, std::ranges::uninitialized_move_result
| ヘッダ <memory> で定義 |
||
| 呼び出しシグネチャ |
||
template< std::input_iterator I, std::sentinel_for<I> S1, no-throw-forward-iterator O, no-throw-sentinel-for<O> S2 > |
(1) | (C++20以降) (C++26 以降 constexpr) |
template< ranges::input_range IR, no-throw-forward-range OR > requires std::constructible_from |
(2) | (C++20以降) (C++26 以降 constexpr) |
| ヘルパー型 |
||
| template< class I, class O > using uninitialized_move_result = ranges::in_out_result<I, O>; |
(3) | (C++20以降) |
Let N be ranges::min(ranges::distance(ifirst, ilast), ranges::distance(ofirst, olast))。
for (; ifirst != ilast && ofirst != olast; ++ofirst, (void)++ifirst)
::new (voidify(*ofirst))
std::remove_reference_t<std::iter_reference_t<O>>(ranges::iter_move(ifirst));
return {std::move(ifirst), ofirst};
ranges::begin(out_range), ranges::end(out_range)); と同等です。
このページで説明されている関数のようなエンティティは、アルゴリズム関数オブジェクト(非公式にはニーブロイドとして知られている)です。つまり、
- これらのいずれかを呼び出す際に、明示的なテンプレート引数リストを指定することはできません。
- これらのいずれも実引数依存の名前探索には見えません。
- これらのいずれかが関数呼び出し演算子の左側の名前として通常の非修飾名探索によって見つかった場合、実引数依存の名前探索は抑制されます。
目次 |
[編集] パラメータ
| ifirst, ilast | - | 移動元の要素の入力範囲を定義するイテレータ-センチネルペア |
| in_range | - | 移動元の入力範囲 |
| ofirst, olast | - | 初期化する要素の出力範囲を定義するイテレータ-センチネルペア |
| out_range | - | 初期化する出力範囲 |
[編集] 戻り値
上記の通り。
[編集] 計算量
線形。Nに線形。
[編集] 例外
変換先範囲の要素の構築時にスローされる例外。
[編集] 注意
実装によっては、出力範囲の値型がTrivialTypeの場合、ranges::copy_nを使用するなどして、`ranges::uninitialized_move`の効率を向上させることができます。
| 機能テストマクロ | 値 | 規格 | 機能 |
|---|---|---|---|
__cpp_lib_raw_memory_algorithms |
202411L |
(C++26) | constexpr は、特殊なメモリアルゴリズムの場合 (1,2) |
[編集] 可能な実装
struct uninitialized_move_fn { template<std::input_iterator I, std::sentinel_for<I> S1, no-throw-forward-iterator O, no-throw-sentinel-for<O> S2> requires std::constructible_from<std::iter_value_t<O>, std::iter_rvalue_reference_t<I>> constexpr ranges::uninitialized_move_result<I, O> operator()(I ifirst, S1 ilast, O ofirst, S2 olast) const { using ValueType = std::remove_reference_t<std::iter_reference_t<O>>; O current{ofirst}; try { for (; !(ifirst == ilast or current == olast); ++ifirst, ++current) ::new (static_cast<void*>(std::addressof(*current)))) ValueType(ranges::iter_move(ifirst)); return {std::move(ifirst), std::move(current)}; } catch (...) // rollback: destroy constructed elements { for (; ofirst != current; ++ofirst) ranges::destroy_at(std::addressof(*ofirst)); throw; } } template<ranges::input_range IR, no-throw-forward-range OR> requires std::constructible_from<ranges::range_value_t<OR>, ranges::range_rvalue_reference_t<IR>> constexpr ranges::uninitialized_move_result<ranges::borrowed_iterator_t<IR>, ranges::borrowed_iterator_t<OR>> operator()(IR&& in_range, OR&& out_range) const { return (*this)(ranges::begin(in_range), ranges::end(in_range), ranges::begin(out_range), ranges::end(out_range)); } }; inline constexpr uninitialized_move_fn uninitialized_move{}; |
[編集] 例
#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[]{"Home", "World"}; 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(std::begin(in), std::end(in), 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: "Home" "World" after move, in: "" "" after move, out: "Home" "World"
[編集] 不具合報告
以下の動作変更を伴う欠陥報告が、以前に公開されたC++標準に遡って適用されました。
| DR | 適用対象 | 公開された動作 | 正しい動作 |
|---|---|---|---|
| LWG 3870 | C++20 | このアルゴリズムは、const ストレージ上にオブジェクトを作成する可能性があります。 | 禁止されたままです。 |
[編集] 関連項目
| (C++20) |
指定された数のオブジェクトを未初期化メモリ領域にムーブします (アルゴリズム関数オブジェクト) |
| (C++17) |
オブジェクトの範囲を未初期化メモリ領域にムーブします (関数テンプレート) |