6868
6969 </ head >
7070 < body >
71- < header data-kunai-mdinfo ="{"meta": {"header": ["memory"], "namespace": ["std"], "id-type": ["class template"], "cpp": ["cpp26"]}, "sources": [{"id": "0cef3c90f94eb384b69e8f07cb4ad81435af3a1a", "source": "#include <cassert>\n#include <memory>\n\nint main()\n{\n // \u52d5\u7684\u78ba\u4fdd\u3057\u305fint\u3092\u3001\u5024\u306e\u610f\u5473\u8ad6\u3067\u4fdd\u6301\u3059\u308b\n std::indirect<int> a{42};\n assert(*a == 42);\n\n // \u30b3\u30d4\u30fc\u306f\u6240\u6709\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u306e\u30c7\u30a3\u30fc\u30d7\u30b3\u30d4\u30fc\n std::indirect<int> b = a;\n *b = 10;\n assert(*a == 42); // a\u306f\u5f71\u97ff\u3092\u53d7\u3051\u306a\u3044\n assert(*b == 10);\n\n // \u6bd4\u8f03\u306f\u6240\u6709\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u306e\u6bd4\u8f03\u306b\u8ee2\u9001\u3055\u308c\u308b\n assert(a == std::indirect<int>{42});\n assert(b < a);\n}\n"}], "page_id": ["reference", "memory", "indirect"]} ">
71+ < header data-kunai-mdinfo ="{"meta": {"header": ["memory"], "namespace": ["std"], "id-type": ["class template"], "cpp": ["cpp26"]}, "sources": [{"id": "0cef3c90f94eb384b69e8f07cb4ad81435af3a1a", "source": "#include <cassert>\n#include <memory>\n\nint main()\n{\n // \u52d5\u7684\u78ba\u4fdd\u3057\u305fint\u3092\u3001\u5024\u306e\u610f\u5473\u8ad6\u3067\u4fdd\u6301\u3059\u308b\n std::indirect<int> a{42};\n assert(*a == 42);\n\n // \u30b3\u30d4\u30fc\u306f\u6240\u6709\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u306e\u30c7\u30a3\u30fc\u30d7\u30b3\u30d4\u30fc\n std::indirect<int> b = a;\n *b = 10;\n assert(*a == 42); // a\u306f\u5f71\u97ff\u3092\u53d7\u3051\u306a\u3044\n assert(*b == 10);\n\n // \u6bd4\u8f03\u306f\u6240\u6709\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u306e\u6bd4\u8f03\u306b\u8ee2\u9001\u3055\u308c\u308b\n assert(a == std::indirect<int>{42});\n assert(b < a);\n}\n"}, {"id": "3eb2d8c7ff47b5dc189c88c4705ae968825518ab", "source": "#include <cassert>\n#include <memory>\n\n// \u30d8\u30c3\u30c0\u76f8\u5f53: \u5b9f\u88c5\u30af\u30e9\u30b9Impl\u306f\u524d\u65b9\u5ba3\u8a00\u306e\u307f\uff08\u4e0d\u5b8c\u5168\u578b\uff09\nclass Widget {\n class Impl;\n std::indirect<Impl> impl_;\npublic:\n Widget(int x);\n int value() const;\n void set(int x);\n // \u30b3\u30d4\u30fc\u30fb\u30e0\u30fc\u30d6\u30fb\u30c7\u30b9\u30c8\u30e9\u30af\u30bf\u306f\u30b3\u30f3\u30d1\u30a4\u30e9\u304c\u751f\u6210\u3059\u308b\n};\n\n// \u5b9f\u88c5\u76f8\u5f53: \u3053\u3053\u3067Impl\u304c\u5b8c\u5168\u578b\u306b\u306a\u308b\nclass Widget::Impl {\npublic:\n int v;\n Impl(int x) : v(x) {}\n};\n\nWidget::Widget(int x) : impl_{std::in_place, x} {}\nint Widget::value() const { return impl_->v; } // const\u304c\u4f1d\u64ad\u3059\u308b\nvoid Widget::set(int x) { impl_->v = x; }\n\nint main()\n{\n Widget a{42};\n assert(a.value() == 42);\n\n Widget b = a; // \u5024\u306e\u30b3\u30d4\u30fc\uff08Impl\u304c\u30c7\u30a3\u30fc\u30d7\u30b3\u30d4\u30fc\u3055\u308c\u308b\uff09\n b.set(10);\n assert(a.value() == 42); // a\u306f\u5f71\u97ff\u3092\u53d7\u3051\u306a\u3044\n assert(b.value() == 10);\n}\n"}], "page_id": ["reference", "memory", "indirect"]} ">
7272 < nav class ="navbar navbar-default " role ="navigation ">
7373 < div class ="container-fluid ">
7474 < div class ="navbar-header ">
188188
189189 < p class ="text-right "> < small >
190190 最終更新日時(UTC):
191- < span itemprop ="datePublished " content ="2026-06-22T07:01:50 ">
192- 2026年06月22日 07時01分50秒
191+ < span itemprop ="datePublished " content ="2026-06-24T02:35:51 ">
192+ 2026年06月24日 02時35分51秒
193193 </ span >
194194 < br />
195195 < span itemprop ="author " itemscope itemtype ="http://schema.org/Person ">
@@ -234,6 +234,7 @@ <h2>概要</h2>
234234< li > < a class ="cpprefjp-defined-word " data-desc ="型のサイズを決定できない、完全には定義されていない型。例えば先行宣言のみのクラス型、要素数不明の配列型、`void`など。クラス定義内部ではそのクラス自身は不完全型 "> 不完全型</ a > のサポート: テンプレートパラメータ< code > T</ code > は< a class ="cpprefjp-defined-word " data-desc ="型のサイズを決定できない、完全には定義されていない型。例えば先行宣言のみのクラス型、要素数不明の配列型、`void`など。クラス定義内部ではそのクラス自身は不完全型 "> 不完全型</ a > でもよい。これにより、再帰的なデータ構造を表現できる</ li >
235235</ ul >
236236< p > これらの性質によって、< code > std::indirect</ code > クラスのオブジェクトはクラスのメンバとして保持するのに適しており、コンパイラによる特殊メンバ関数の自動生成と協調して動作する。</ p >
237+ < p > とくに、pImplイディオム(実装クラスへのポインタをメンバとしてもち、実装詳細をヘッダから隠蔽してソースファイル側で行う手法)の実装に適している。実装クラスを< a class ="cpprefjp-defined-word " data-desc ="型のサイズを決定できない、完全には定義されていない型。例えば先行宣言のみのクラス型、要素数不明の配列型、`void`など。クラス定義内部ではそのクラス自身は不完全型 "> 不完全型</ a > のまま< code > std::indirect</ code > 型でメンバ変数として保持すると、生のポインタや< code > < a href ="unique_ptr.html "> std::unique_ptr</ a > </ code > で実装した場合とは異なり、値のコピー(実装クラスのディープコピー)と< code > const</ code > の伝播がともに自動的に正しく行われる。</ p >
237238< p > 所有オブジェクトを持たない状態を「無効値状態 (valueless state)」と呼ぶ。< code > std::indirect</ code > オブジェクトが無効値状態になるのは、ムーブ後に空となった場合のみである。無効値状態のオブジェクトに対する< code > operator*</ code > や< code > operator-></ code > の呼び出しは< a class ="cpprefjp-defined-word " data-desc ="未定義の動作。処理系は予期せぬ動作をする可能性がある。要するに動作保証対象外。undefined behavior (UB)。 " href ="../../implementation-compliance.html#dfn-undefined-behavior "> 未定義動作</ a > を引き起こす。無効値状態かどうかは< code > < a href ="indirect/valueless_after_move.html "> valueless_after_move()</ a > </ code > メンバ関数で判定できる。</ p >
238239< p > 派生型のオブジェクトを多態的に保持したい場合は、< code > < a href ="polymorphic.html "> std::polymorphic</ a > </ code > クラスを使用する。</ p >
239240< h2 > < a class ="cpprefjp-defined-word " data-desc ="関数等の意味論を構成する要素の1つ。Constraints。関数であればオーバーロード解決に参加するための条件、それ以外であれば受け付ける型の条件 "> テンプレートパラメータ制約</ a > </ h2 >
@@ -436,6 +437,7 @@ <h2>ハッシュサポート</h2>
436437</ tbody >
437438</ table >
438439< h2 > 例</ h2 >
440+ < h3 > 基本的な使い方</ h3 >
439441< p > < div class ="yata " id ="0cef3c90f94eb384b69e8f07cb4ad81435af3a1a "> < div class ="codehilite "> < pre > < span > </ span > < code > < span class ="cp "> #include < a href ="../cassert.html "> <cassert></ a > </ span >
440442< span class ="cp "> #include < a href ="../memory.html "> <memory></ a > </ span >
441443
@@ -459,6 +461,47 @@ <h2>例</h2>
459461</ div > </ p >
460462< h3 > 出力</ h3 >
461463< p > < pre > < code > </ code > </ pre > </ p >
464+ < h3 > pImplイディオムでの使用</ h3 >
465+ < p > 実装クラスを< a class ="cpprefjp-defined-word " data-desc ="型のサイズを決定できない、完全には定義されていない型。例えば先行宣言のみのクラス型、要素数不明の配列型、`void`など。クラス定義内部ではそのクラス自身は不完全型 "> 不完全型</ a > のまま< code > std::indirect</ code > で保持することで、値の意味論をもつpImplを簡潔に実装できる。コピー・ムーブ・デストラクタはコンパイラが生成し、< code > const</ code > メンバ関数からは実装クラスにも< code > const</ code > が伝播する。</ p >
466+ < p > < div class ="yata " id ="3eb2d8c7ff47b5dc189c88c4705ae968825518ab "> < div class ="codehilite "> < pre > < span > </ span > < code > < span class ="cp "> #include < a href ="../cassert.html "> <cassert></ a > </ span >
467+ < span class ="cp "> #include < a href ="../memory.html "> <memory></ a > </ span >
468+
469+ < span class ="c1 "> // ヘッダ相当: 実装クラスImplは前方宣言のみ(不完全型)</ span >
470+ < span class ="k "> class</ span > < span class ="w "> </ span > < span class ="nc "> Widget</ span > < span class ="w "> </ span > < span class ="p "> {</ span >
471+ < span class ="w "> </ span > < span class ="k "> class</ span > < span class ="w "> </ span > < span class ="nc "> Impl</ span > < span class ="p "> ;</ span >
472+ < span class ="w "> </ span > < span class ="n "> < span style ="color:#ff0000 "> std::indirect</ span > </ span > < span class ="o "> <</ span > < span class ="n "> Impl</ span > < span class ="o "> ></ span > < span class ="w "> </ span > < span class ="n "> impl_</ span > < span class ="p "> ;</ span >
473+ < span class ="k "> public</ span > < span class ="o "> :</ span >
474+ < span class ="w "> </ span > < span class ="n "> Widget</ span > < span class ="p "> (</ span > < span class ="kt "> int</ span > < span class ="w "> </ span > < span class ="n "> x</ span > < span class ="p "> );</ span >
475+ < span class ="w "> </ span > < span class ="kt "> int</ span > < span class ="w "> </ span > < span class ="nf "> value</ span > < span class ="p "> ()</ span > < span class ="w "> </ span > < span class ="k "> const</ span > < span class ="p "> ;</ span >
476+ < span class ="w "> </ span > < span class ="kt "> void</ span > < span class ="w "> </ span > < span class ="nf "> set</ span > < span class ="p "> (</ span > < span class ="kt "> int</ span > < span class ="w "> </ span > < span class ="n "> x</ span > < span class ="p "> );</ span >
477+ < span class ="w "> </ span > < span class ="c1 "> // コピー・ムーブ・デストラクタはコンパイラが生成する</ span >
478+ < span class ="p "> };</ span >
479+
480+ < span class ="c1 "> // 実装相当: ここでImplが完全型になる</ span >
481+ < span class ="k "> class</ span > < span class ="w "> </ span > < span class ="nc "> Widget</ span > < span class ="o "> ::</ span > < span class ="n "> Impl</ span > < span class ="w "> </ span > < span class ="p "> {</ span >
482+ < span class ="k "> public</ span > < span class ="o "> :</ span >
483+ < span class ="w "> </ span > < span class ="kt "> int</ span > < span class ="w "> </ span > < span class ="n "> v</ span > < span class ="p "> ;</ span >
484+ < span class ="w "> </ span > < span class ="n "> Impl</ span > < span class ="p "> (</ span > < span class ="kt "> int</ span > < span class ="w "> </ span > < span class ="n "> x</ span > < span class ="p "> )</ span > < span class ="w "> </ span > < span class ="o "> :</ span > < span class ="w "> </ span > < span class ="n "> v</ span > < span class ="p "> (</ span > < span class ="n "> x</ span > < span class ="p "> )</ span > < span class ="w "> </ span > < span class ="p "> {}</ span >
485+ < span class ="p "> };</ span >
486+
487+ < span class ="n "> Widget</ span > < span class ="o "> ::</ span > < span class ="n "> Widget</ span > < span class ="p "> (</ span > < span class ="kt "> int</ span > < span class ="w "> </ span > < span class ="n "> x</ span > < span class ="p "> )</ span > < span class ="w "> </ span > < span class ="o "> :</ span > < span class ="w "> </ span > < span class ="n "> impl_</ span > < span class ="p "> {</ span > < span class ="n "> < a href ="../utility/in_place_t.html "> std::in_place</ a > </ span > < span class ="p "> ,</ span > < span class ="w "> </ span > < span class ="n "> x</ span > < span class ="p "> }</ span > < span class ="w "> </ span > < span class ="p "> {}</ span >
488+ < span class ="kt "> int</ span > < span class ="w "> </ span > < span class ="n "> Widget</ span > < span class ="o "> ::</ span > < span class ="n "> value</ span > < span class ="p "> ()</ span > < span class ="w "> </ span > < span class ="k "> const</ span > < span class ="w "> </ span > < span class ="p "> {</ span > < span class ="w "> </ span > < span class ="k "> return</ span > < span class ="w "> </ span > < span class ="n "> impl_</ span > < span class ="o "> -></ span > < span class ="n "> v</ span > < span class ="p "> ;</ span > < span class ="w "> </ span > < span class ="p "> }</ span > < span class ="w "> </ span > < span class ="c1 "> // constが伝播する</ span >
489+ < span class ="kt "> void</ span > < span class ="w "> </ span > < span class ="n "> Widget</ span > < span class ="o "> ::</ span > < span class ="n "> set</ span > < span class ="p "> (</ span > < span class ="kt "> int</ span > < span class ="w "> </ span > < span class ="n "> x</ span > < span class ="p "> )</ span > < span class ="w "> </ span > < span class ="p "> {</ span > < span class ="w "> </ span > < span class ="n "> impl_</ span > < span class ="o "> -></ span > < span class ="n "> v</ span > < span class ="w "> </ span > < span class ="o "> =</ span > < span class ="w "> </ span > < span class ="n "> x</ span > < span class ="p "> ;</ span > < span class ="w "> </ span > < span class ="p "> }</ span >
490+
491+ < span class ="kt "> int</ span > < span class ="w "> </ span > < span class ="n "> main</ span > < span class ="p "> ()</ span >
492+ < span class ="p "> {</ span >
493+ < span class ="w "> </ span > < span class ="n "> Widget</ span > < span class ="w "> </ span > < span class ="n "> a</ span > < span class ="p "> {</ span > < span class ="mi "> 42</ span > < span class ="p "> };</ span >
494+ < span class ="w "> </ span > < span class ="n "> < a href ="../cassert/assert.html "> assert</ a > </ span > < span class ="p "> (</ span > < span class ="n "> a</ span > < span class ="p "> .</ span > < span class ="n "> value</ span > < span class ="p "> ()</ span > < span class ="w "> </ span > < span class ="o "> ==</ span > < span class ="w "> </ span > < span class ="mi "> 42</ span > < span class ="p "> );</ span >
495+
496+ < span class ="w "> </ span > < span class ="n "> Widget</ span > < span class ="w "> </ span > < span class ="n "> b</ span > < span class ="w "> </ span > < span class ="o "> =</ span > < span class ="w "> </ span > < span class ="n "> a</ span > < span class ="p "> ;</ span > < span class ="w "> </ span > < span class ="c1 "> // 値のコピー(Implがディープコピーされる)</ span >
497+ < span class ="w "> </ span > < span class ="n "> b</ span > < span class ="p "> .</ span > < span class ="n "> set</ span > < span class ="p "> (</ span > < span class ="mi "> 10</ span > < span class ="p "> );</ span >
498+ < span class ="w "> </ span > < span class ="n "> < a href ="../cassert/assert.html "> assert</ a > </ span > < span class ="p "> (</ span > < span class ="n "> a</ span > < span class ="p "> .</ span > < span class ="n "> value</ span > < span class ="p "> ()</ span > < span class ="w "> </ span > < span class ="o "> ==</ span > < span class ="w "> </ span > < span class ="mi "> 42</ span > < span class ="p "> );</ span > < span class ="w "> </ span > < span class ="c1 "> // aは影響を受けない</ span >
499+ < span class ="w "> </ span > < span class ="n "> < a href ="../cassert/assert.html "> assert</ a > </ span > < span class ="p "> (</ span > < span class ="n "> b</ span > < span class ="p "> .</ span > < span class ="n "> value</ span > < span class ="p "> ()</ span > < span class ="w "> </ span > < span class ="o "> ==</ span > < span class ="w "> </ span > < span class ="mi "> 10</ span > < span class ="p "> );</ span >
500+ < span class ="p "> }</ span >
501+ </ code > </ pre > </ div >
502+ </ div > </ p >
503+ < h3 > 出力</ h3 >
504+ < p > < pre > < code > </ code > </ pre > </ p >
462505< h2 > バージョン</ h2 >
463506< h3 > 言語</ h3 >
464507< ul >
0 commit comments