次期C++2b(C++23)標準ライブラリのコルーチンサポート型std::generator<Ref>
(→id:yohhoy:20220801)の第1テンプレートパラメータRef
と、オブジェクトのコピー/ムーブの関係性についてメモ。
まとめ:
- 利用側にconst参照を提供:const-lvalue参照
const T&
を指定。 - 利用側に可変参照を提供:lvalue参照
T&
を指定。 - ムーブのみ(Move-only)型:値型
T
またはrvalue参照型T&&
を指定。- 実動作は両者で同一。“ムーブ” 動作を示唆する
T&&
の方が好ましい?
- 実動作は両者で同一。“ムーブ” 動作を示唆する
- プリミティブ型など*1:値型
T
を指定。 - 利用側の範囲for:
auto&&
(→id:yohhoy:20120609)またはconst auto&
を推奨。
テンプレートパラメータRef
に値型T
またはその参照型を指定した場合*2、各箇所において発生するコピー/ムーブは下表のとおり:
Ref | yield-v | yield-cv | yield-rv | consume-v |
---|---|---|---|---|
T |
1 copy | 1 copy | 0 | 1 move |
T&& |
1 copy | 1 copy | 0 | 1 move |
T& |
1 copy | 1 copy | (ill-formed) | 1 copy |
const T& |
0 | 0 | 0 | 1 copy |
凡例:0=コピー/ムーブなし、(ill-formed)=コンパイルエラー
// C++2b #include <generator> // ユーザ定義コルーチン std::generator<??> gen() { T v; co_yield v; // yield-v const T cv; co_yield cv; // yield-cv // yield-rv co_yield T{}; co_yield std::move(v); } // 利用側コード void consumer() { // consume-v for (auto v: gen()) { ... } // 下記2パターンは常にコピー/ムーブ発生しない for (const auto& cr: gen()) { ... } for (auto&& ur: gen()) { ... } }
ノート:コルーチン内でco_yield std::move(v);
を記述しても、即座にはムーブ処理が行われないことに留意。Ref
=T
/T&&
であれば利用側コードでムーブ処理が行われる。
関連URL