From cff22113c8f884df3e65c2d23570ba6dc92e1fec Mon Sep 17 00:00:00 2001 From: Akira Takahashi Date: Mon, 22 Jun 2026 16:01:50 +0900 Subject: [PATCH] =?UTF-8?q?C++26=E5=AF=BE=E5=BF=9C=E3=81=A8=E3=81=97?= =?UTF-8?q?=E3=81=A6indirect=E3=81=A8polymorphic=E3=81=AE=E3=83=AA?= =?UTF-8?q?=E3=83=95=E3=82=A1=E3=83=AC=E3=83=B3=E3=82=B9=E3=82=92=E4=BD=9C?= =?UTF-8?q?=E6=88=90=20#1430?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lang/cpp26.md | 2 +- lang/cpp26/feature_test_macros.md | 4 +- reference/memory.md | 8 + reference/memory/indirect.md | 165 ++++++++++++++++++ reference/memory/indirect/get_allocator.md | 39 +++++ reference/memory/indirect/hash.md | 66 +++++++ reference/memory/indirect/op_arrow.md | 65 +++++++ reference/memory/indirect/op_assign.md | 97 ++++++++++ reference/memory/indirect/op_compare_3way.md | 72 ++++++++ reference/memory/indirect/op_constructor.md | 156 +++++++++++++++++ .../memory/indirect/op_deduction_guide.md | 59 +++++++ reference/memory/indirect/op_deref.md | 72 ++++++++ reference/memory/indirect/op_destructor.md | 39 +++++ reference/memory/indirect/op_equal.md | 75 ++++++++ reference/memory/indirect/swap.md | 69 ++++++++ reference/memory/indirect/swap_free.md | 63 +++++++ .../memory/indirect/valueless_after_move.md | 61 +++++++ reference/memory/polymorphic.md | 147 ++++++++++++++++ reference/memory/polymorphic/get_allocator.md | 39 +++++ reference/memory/polymorphic/op_arrow.md | 74 ++++++++ reference/memory/polymorphic/op_assign.md | 93 ++++++++++ .../memory/polymorphic/op_constructor.md | 158 +++++++++++++++++ reference/memory/polymorphic/op_deref.md | 75 ++++++++ reference/memory/polymorphic/op_destructor.md | 39 +++++ reference/memory/polymorphic/swap.md | 74 ++++++++ reference/memory/polymorphic/swap_free.md | 68 ++++++++ .../polymorphic/valueless_after_move.md | 72 ++++++++ 27 files changed, 1948 insertions(+), 3 deletions(-) create mode 100644 reference/memory/indirect.md create mode 100644 reference/memory/indirect/get_allocator.md create mode 100644 reference/memory/indirect/hash.md create mode 100644 reference/memory/indirect/op_arrow.md create mode 100644 reference/memory/indirect/op_assign.md create mode 100644 reference/memory/indirect/op_compare_3way.md create mode 100644 reference/memory/indirect/op_constructor.md create mode 100644 reference/memory/indirect/op_deduction_guide.md create mode 100644 reference/memory/indirect/op_deref.md create mode 100644 reference/memory/indirect/op_destructor.md create mode 100644 reference/memory/indirect/op_equal.md create mode 100644 reference/memory/indirect/swap.md create mode 100644 reference/memory/indirect/swap_free.md create mode 100644 reference/memory/indirect/valueless_after_move.md create mode 100644 reference/memory/polymorphic.md create mode 100644 reference/memory/polymorphic/get_allocator.md create mode 100644 reference/memory/polymorphic/op_arrow.md create mode 100644 reference/memory/polymorphic/op_assign.md create mode 100644 reference/memory/polymorphic/op_constructor.md create mode 100644 reference/memory/polymorphic/op_deref.md create mode 100644 reference/memory/polymorphic/op_destructor.md create mode 100644 reference/memory/polymorphic/swap.md create mode 100644 reference/memory/polymorphic/swap_free.md create mode 100644 reference/memory/polymorphic/valueless_after_move.md diff --git a/lang/cpp26.md b/lang/cpp26.md index c363aa1d53..09709d8845 100644 --- a/lang/cpp26.md +++ b/lang/cpp26.md @@ -360,7 +360,7 @@ C++26とは、2026年中に改訂される予定の、C++バージョンの通 ### スマートポインタ・メモリ関連 -- 動的確保したオブジェクトに値の意味論をもたせてディープコピーさせるユーティリティクラスとして、[``](/reference/memory.md)に[`std::indirect`](/reference/memory/indirect.md.nolink)クラスと[`std::polymorphic`](/reference/memory/polymorphic.md.nolink)クラスを追加 +- 動的確保したオブジェクトに値の意味論をもたせてディープコピーさせるユーティリティクラスとして、[``](/reference/memory.md)に[`std::indirect`](/reference/memory/indirect.md)クラスと[`std::polymorphic`](/reference/memory/polymorphic.md)クラスを追加 - [`std::weak_ptr`](/reference/memory/weak_ptr.md)を非順序連想コンテナのキーとして使用できるよう、[``](/reference/memory.md)に所有権ベースのハッシュ値を取得する関数オブジェクト[`std::owner_hash`](/reference/memory/owner_hash.md)、および所有権ベースの等値比較を行う関数オブジェクト[`std::owner_equal`](/reference/memory/owner_equal.md)を追加 - 関連して、[`std::shared_ptr`](/reference/memory/shared_ptr.md)クラスと[`std::weak_ptr`](/reference/memory/weak_ptr.md)クラスのメンバ関数として、`owner_hash()`と`owner_equal()`を追加 - [`std::shared_ptr`](/reference/memory/shared_ptr.md)クラスとその関連機能を`constexpr`対応 diff --git a/lang/cpp26/feature_test_macros.md b/lang/cpp26/feature_test_macros.md index 9b9b357ea4..2c2595ea8d 100755 --- a/lang/cpp26/feature_test_macros.md +++ b/lang/cpp26/feature_test_macros.md @@ -109,7 +109,7 @@ |`__cpp_lib_function_ref`|`202306L`|[``](/reference/functional.md)に[`std::function_ref`](/reference/functional/function_ref.md)を追加|[``](/reference/functional.md)| |`__cpp_lib_hazard_pointer`|`202306L`|ハザードポインタのライブラリ[``](/reference/hazard_pointer.md.nolink)を追加|[``](/reference/hazard_pointer.md.nolink)| |`__cpp_lib_hive`|`202502L`|シーケンスコンテナのライブラリ[``](/reference/hive.md.nolink)を追加|[``](/reference/hive.md.nolink)| -|`__cpp_lib_indirect`|`202502L`|[``](/reference/memory.md)に[`std::indirect`](/reference/memory/indirect.md.nolink)と[`std::polymorphic`](/reference/memory/polymorphic.md.nolink)を追加|[``](/reference/memory.md)| +|`__cpp_lib_indirect`|`202502L`|[``](/reference/memory.md)に[`std::indirect`](/reference/memory/indirect.md)と[`std::polymorphic`](/reference/memory/polymorphic.md)を追加|[``](/reference/memory.md)| |`__cpp_lib_inplace_vector`|`202603L`|容量固定の可変長配列のライブラリ[``](/reference/inplace_vector.md)を追加|[``](/reference/inplace_vector.md)| |`__cpp_lib_integer_sequence`|`202511L`|[`std::integer_sequence`](/reference/utility/integer_sequence.md)を[構造化束縛](/lang/cpp17/structured_bindings.md)と[`template for`文](/lang/cpp26/expansion_statements.md)で使用できるよう、タプルインタフェースの特殊化を追加|[``](/reference/utility.md)| |`__cpp_lib_is_sufficiently_aligned`|`202411L`|[``](/reference/mdspan.md)に、要素アクセスにアライメント保証を与える[`std::aligned_accessor`](/reference/mdspan/aligned_accessor.md)を追加|[``](/reference/memory.md)| @@ -126,7 +126,7 @@ |`__cpp_lib_parallel_algorithm`|`202506L`|[``](/reference/algorithm.md)と[``](/reference/memory.md)のアルゴリズムを並列実行に対応|[``](/reference/algorithm.md), [``](/reference/numeric.md), [``](/reference/memory.md)| |`__cpp_lib_parallel_scheduler`|`202506L`|[``](/reference/execution.md)に[`std::execution::parallel_scheduler`](/reference/execution/execution/parallel_scheduler.md)を追加|[``](/reference/execution.md)| |`__cpp_lib_philox_engine`|`202406L`|[``](/reference/random.md)に[`std::philox_engine`](/reference/random/philox_engine.md)、[`std::philox4x32`](/reference/random/philox4x32.md)、[`std::philox4x64`](/reference/random/philox4x64.md)を追加|[``](/reference/random.md)| -|`__cpp_lib_polymorphic`|`202502L`|[``](/reference/memory.md)に[`std::indirect`](/reference/memory/indirect.md.nolink)と[`std::polymorphic`](/reference/memory/polymorphic.md.nolink)を追加|[``](/reference/memory.md)| +|`__cpp_lib_polymorphic`|`202502L`|[``](/reference/memory.md)に[`std::indirect`](/reference/memory/indirect.md)と[`std::polymorphic`](/reference/memory/polymorphic.md)を追加|[``](/reference/memory.md)| |`__cpp_lib_print`|`202406L`|[`std::print()`](/reference/print/print.md)と[`std::println()`](/reference/print/println.md)にロックを取得せず高速に書き出す最適化を許可
[`std::enable_nonlocking_formatter_optimization`](/reference/format/enable_nonlocking_formatter_optimization.md)を追加|[``](/reference/print.md), [``](/reference/ostream.md)| |`__cpp_lib_ranges`|`202406L`|[`std::indirectly_unary_invocable`](/reference/iterator/indirectly_unary_invocable.md)などのコンセプトの共通参照要件を削除|[``](/reference/algorithm.md), [``](/reference/functional.md), [``](/reference/iterator.md), [``](/reference/memory.md), [``](/reference/ranges.md)| |`__cpp_lib_ranges_as_const`|`202311L`|[`std::basic_const_iterator`](/reference/iterator/basic_const_iterator.md)を元の要素へのキャストを可能にする|[``](/reference/ranges.md)| diff --git a/reference/memory.md b/reference/memory.md index ace4a60a88..70a9b871d5 100644 --- a/reference/memory.md +++ b/reference/memory.md @@ -101,6 +101,14 @@ | [`inout_ptr`](memory/inout_ptr.md) | スマートポインタへの入出力サポートヘルパ関数(function template) | C++23 | +## 値の意味論をもつ間接ストレージ + +| 名前 | 説明 | 対応バージョン | +|------|------|----------------| +| [`indirect`](memory/indirect.md) | 動的確保したオブジェクトに値の意味論をもたせるクラス(class template) | C++26 | +| [`polymorphic`](memory/polymorphic.md) | 動的確保したオブジェクトに値の意味論をもたせ、派生型を多態的に保持するクラス(class template) | C++26 | + + ## スマートポインタのアトミック操作 | 名前 | 説明 | 対応バージョン | diff --git a/reference/memory/indirect.md b/reference/memory/indirect.md new file mode 100644 index 0000000000..50bd4fd58d --- /dev/null +++ b/reference/memory/indirect.md @@ -0,0 +1,165 @@ +# indirect +* memory[meta header] +* std[meta namespace] +* class template[meta id-type] +* cpp26[meta cpp] + +```cpp +namespace std { + template > + class indirect; + + namespace pmr { + template + using indirect = std::indirect>; + } +} +``` +* allocator[link allocator.md] +* polymorphic_allocator[link /reference/memory_resource/polymorphic_allocator.md] + +## 概要 +`std::indirect`クラスは、動的確保したオブジェクトに値の意味論をもたせる型である。 + +ポインタやスマートポインタは参照の意味論をもつため、クラスのメンバとして使うとコピーや`const`の伝播が正しく行われず、クラスの特殊メンバ関数を正しく生成できないことがある。 + +`std::indirect`クラスは所有するオブジェクトを動的確保しつつ、以下のように値型として振る舞う: + +- ディープコピー: `std::indirect`オブジェクトをコピーすると、所有するオブジェクト`T`がそのコピーコンストラクタによって複製される +- `const`の伝播: `const`なアクセス経路から所有オブジェクトにアクセスすると、所有オブジェクトにも`const`が伝播する(`operator*`/`operator->`に`const`版と非`const`版がある) +- 不完全型のサポート: テンプレートパラメータ`T`は不完全型でもよい。これにより、再帰的なデータ構造を表現できる + +これらの性質によって、`std::indirect`クラスのオブジェクトはクラスのメンバとして保持するのに適しており、コンパイラによる特殊メンバ関数の自動生成と協調して動作する。 + +所有オブジェクトを持たない状態を「無効値状態 (valueless state)」と呼ぶ。`std::indirect`オブジェクトが無効値状態になるのは、ムーブ後に空となった場合のみである。無効値状態のオブジェクトに対する`operator*`や`operator->`の呼び出しは未定義動作を引き起こす。無効値状態かどうかは[`valueless_after_move()`](indirect/valueless_after_move.md)メンバ関数で判定できる。 + +派生型のオブジェクトを多態的に保持したい場合は、[`std::polymorphic`](polymorphic.md)クラスを使用する。 + + +## テンプレートパラメータ制約 +- `Allocator`はCpp17Allocator要件を満たすこと +- [`std::allocator_traits`](/reference/memory/allocator_traits.md)`::value_type`が`T`と同じ型であること + + +## 適格要件 +- 以下のいずれかの場合に、プログラムは不適格となる + - `T`がオブジェクト型でない + - 配列型である + - (CV修飾された) [`std::in_place_t`](/reference/utility/in_place_t.md)である + - (CV修飾された) [`std::in_place_type_t`](/reference/utility/in_place_type_t.md)の特殊化である +- `std::indirect`の明示的特殊化・部分特殊化をユーザーが宣言した場合、動作は未定義である + + +## メンバ関数 +### 構築・破棄 + +| 名前 | 説明 | 対応バージョン | +|------|------|----------------| +| [`(constructor)`](indirect/op_constructor.md) | コンストラクタ | C++26 | +| [`(destructor)`](indirect/op_destructor.md) | デストラクタ | C++26 | +| [`operator=`](indirect/op_assign.md) | 代入演算子 | C++26 | + +### 値へのアクセス + +| 名前 | 説明 | 対応バージョン | +|------|------|----------------| +| [`operator*`](indirect/op_deref.md) | 所有するオブジェクトへの参照を取得する | C++26 | +| [`operator->`](indirect/op_arrow.md) | 所有するオブジェクトのメンバへアクセスする | C++26 | +| [`valueless_after_move`](indirect/valueless_after_move.md) | 無効値状態かどうかを判定する | C++26 | + +### その他 + +| 名前 | 説明 | 対応バージョン | +|------|------|----------------| +| [`get_allocator`](indirect/get_allocator.md) | アロケータを取得する | C++26 | +| [`swap`](indirect/swap.md) | 他の`indirect`オブジェクトと値を交換する | C++26 | + + +## メンバ型 + +| 名前 | 定義 | 対応バージョン | +|------|------|----------------| +| `value_type` | `T` | C++26 | +| `allocator_type` | `Allocator` | C++26 | +| `pointer` | [`allocator_traits`](/reference/memory/allocator_traits.md)`::pointer` | C++26 | +| `const_pointer` | [`allocator_traits`](/reference/memory/allocator_traits.md)`::const_pointer` | C++26 | + + +## 非メンバ(*Hidden friends*)関数 + +| 名前 | 説明 | 対応バージョン | +|------|------|----------------| +| [`swap`](indirect/swap_free.md) | 2つの`indirect`オブジェクトを交換する | C++26 | + +### 比較演算子 + +| 名前 | 説明 | 対応バージョン | +|------|------|----------------| +| [`operator==`](indirect/op_equal.md) | 等値比較を行う | C++26 | +| [`operator<=>`](indirect/op_compare_3way.md) | 三方比較を行う | C++26 | + +`operator==`から`operator!=`が、`operator<=>`から`operator<` / `operator<=` / `operator>` / `operator>=`が導出される。 + + +## 推論補助 + +| 名前 | 説明 | 対応バージョン | +|------|------|----------------| +| [`(deduction_guide)`](indirect/op_deduction_guide.md) | クラステンプレートの推論補助 | C++26 | + + +## ハッシュサポート + +| 名前 | 説明 | 対応バージョン | +|------|------|----------------| +| [`hash`](indirect/hash.md) | `hash`クラスの特殊化 | C++26 | + + +## 例 +```cpp example +#include +#include + +int main() +{ + // 動的確保したintを、値の意味論で保持する + std::indirect a{42}; + assert(*a == 42); + + // コピーは所有オブジェクトのディープコピー + std::indirect b = a; + *b = 10; + assert(*a == 42); // aは影響を受けない + assert(*b == 10); + + // 比較は所有オブジェクトの比較に転送される + assert(a == std::indirect{42}); + assert(b < a); +} +``` +* std::indirect[color ff0000] + +### 出力 +``` +``` + + +## バージョン +### 言語 +- C++26 + +### 処理系 +- [Clang](/implementation.md#clang): 22 [mark noimpl] +- [GCC](/implementation.md#gcc): 16.1 [mark verified] +- [Visual C++](/implementation.md#visual_cpp): 2026 Update 2 [mark noimpl] + + +## 関連項目 +- [`std::polymorphic`](polymorphic.md) 派生型を多態的に保持する値型 +- [`std::unique_ptr`](unique_ptr.md) 所有権をもつが参照の意味論をもつスマートポインタ +- [`std::optional`](/reference/optional/optional.md) 動的確保せずに無効値状態を表現する型 + + +## 参照 +- [P3019R14 `indirect` and `polymorphic`: Vocabulary Types for Composite Class Design](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3019r14.pdf) + - C++26で`indirect`と`polymorphic`が追加された diff --git a/reference/memory/indirect/get_allocator.md b/reference/memory/indirect/get_allocator.md new file mode 100644 index 0000000000..f51c173bcd --- /dev/null +++ b/reference/memory/indirect/get_allocator.md @@ -0,0 +1,39 @@ +# get_allocator +* memory[meta header] +* std[meta namespace] +* indirect[meta class] +* function[meta id-type] +* cpp26[meta cpp] + +```cpp +constexpr allocator_type get_allocator() const noexcept; +``` + +## 概要 +このオブジェクトが使用するアロケータを取得する。 + + +## 戻り値 +所有するアロケータのコピー。 + + +## 例外 +投げない。 + + +## バージョン +### 言語 +- C++26 + +### 処理系 +- [Clang](/implementation.md#clang): 22 [mark noimpl] +- [GCC](/implementation.md#gcc): 16.1 [mark verified] +- [Visual C++](/implementation.md#visual_cpp): 2026 Update 2 [mark noimpl] + + +## 関連項目 +- [`std::indirect`](../indirect.md) + + +## 参照 +- [P3019R14 `indirect` and `polymorphic`: Vocabulary Types for Composite Class Design](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3019r14.pdf) diff --git a/reference/memory/indirect/hash.md b/reference/memory/indirect/hash.md new file mode 100644 index 0000000000..6aa893188d --- /dev/null +++ b/reference/memory/indirect/hash.md @@ -0,0 +1,66 @@ +# hash +* memory[meta header] +* std[meta namespace] +* indirect[meta class] +* class template[meta id-type] +* cpp26[meta cpp] + +```cpp +namespace std { + template + struct hash>; +} +``` +* hash[link /reference/functional/hash.md] + +## 概要 +[`std::hash`](/reference/functional/hash.md)クラスの、`std::indirect`に対する特殊化。 + +この特殊化は、`hash`が有効である場合にのみ有効となる。 + + +## 効果 +`indirect`型のオブジェクト`i`に対して、`hash>()(i)`は、`i`が無効値状態でなければ`hash()(*i)`と同じ値を返し、無効値状態であれば処理系定義の値を返す。 + + +## 備考 +メンバ関数が`noexcept`である保証はない。 + + +## 例 +```cpp example +#include +#include +#include + +int main() +{ + std::indirect a{42}; + // 所有する値のハッシュ値と一致する + assert((std::hash>{}(a) == std::hash{}(42))); +} +``` +* std::indirect[color ff0000] +* std::hash[link /reference/functional/hash.md] + +### 出力 +``` +``` + + +## バージョン +### 言語 +- C++26 + +### 処理系 +- [Clang](/implementation.md#clang): 22 [mark noimpl] +- [GCC](/implementation.md#gcc): 16.1 [mark verified] +- [Visual C++](/implementation.md#visual_cpp): 2026 Update 2 [mark noimpl] + + +## 関連項目 +- [`std::indirect`](../indirect.md) + + +## 参照 +- [P3019R14 `indirect` and `polymorphic`: Vocabulary Types for Composite Class Design](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3019r14.pdf) diff --git a/reference/memory/indirect/op_arrow.md b/reference/memory/indirect/op_arrow.md new file mode 100644 index 0000000000..a04a30351b --- /dev/null +++ b/reference/memory/indirect/op_arrow.md @@ -0,0 +1,65 @@ +# operator-> +* memory[meta header] +* std[meta namespace] +* indirect[meta class] +* function[meta id-type] +* cpp26[meta cpp] + +```cpp +constexpr const_pointer operator->() const noexcept; // (1) +constexpr pointer operator->() noexcept; // (2) +``` + +## 概要 +所有するオブジェクトのメンバへアクセスするためのポインタを取得する。 + + +## 事前条件 +`*this`が無効値状態でないこと。 + + +## 戻り値 +所有するオブジェクトを指すポインタ。 + + +## 例外 +投げない。 + + +## 例 +```cpp example +#include +#include +#include + +int main() +{ + std::indirect s{std::string{"hello"}}; + assert(s->size() == 5); // 所有するstringのメンバにアクセス + s->push_back('!'); + assert(*s == "hello!"); +} +``` +* std::indirect[color ff0000] + +### 出力 +``` +``` + + +## バージョン +### 言語 +- C++26 + +### 処理系 +- [Clang](/implementation.md#clang): 22 [mark noimpl] +- [GCC](/implementation.md#gcc): 16.1 [mark verified] +- [Visual C++](/implementation.md#visual_cpp): 2026 Update 2 [mark noimpl] + + +## 関連項目 +- [`std::indirect`](../indirect.md) + + +## 参照 +- [P3019R14 `indirect` and `polymorphic`: Vocabulary Types for Composite Class Design](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3019r14.pdf) diff --git a/reference/memory/indirect/op_assign.md b/reference/memory/indirect/op_assign.md new file mode 100644 index 0000000000..7048d1edad --- /dev/null +++ b/reference/memory/indirect/op_assign.md @@ -0,0 +1,97 @@ +# 代入演算子 +* memory[meta header] +* std[meta namespace] +* indirect[meta class] +* function[meta id-type] +* cpp26[meta cpp] + +```cpp +constexpr indirect& operator=(const indirect& other); // (1) +constexpr indirect& operator=(indirect&& other) noexcept(see below); // (2) +template +constexpr indirect& operator=(U&& u); // (3) +``` + +## 概要 +- (1) : コピー代入。`other`が所有するオブジェクトをディープコピーする。 +- (2) : ムーブ代入。`other`から所有権を移す。 +- (3) : 所有するオブジェクトに値`u`を代入する。 + + +## テンプレートパラメータ制約 +- (3) : [`remove_cvref_t`](/reference/type_traits/remove_cvref.md)``が`indirect`でなく、[`is_constructible_v`](/reference/type_traits/is_constructible.md)``と[`is_assignable_v`](/reference/type_traits/is_assignable.md)``がともに`true`であること。 + + +## 適格要件 +- (1) : [`is_copy_assignable_v`](/reference/type_traits/is_copy_assignable.md)``と[`is_copy_constructible_v`](/reference/type_traits/is_copy_constructible.md)``がともに`true`であること。 +- (2) : [`is_copy_constructible_v`](/reference/type_traits/is_copy_constructible.md)``が`true`であること。 + + +## 効果 +- (1) : `other`が無効値状態であれば`*this`も無効値状態にする。そうでなければ、アロケータの伝播規則に従い、`other`が所有するオブジェクトのコピーを`*this`がもつようにする。 +- (2) : `other`が無効値状態であれば`*this`も無効値状態にする。そうでなければ、所有権を移すかムーブ構築する。`other`は無効値状態となる。 +- (3) : `*this`が無効値状態であれば`u`から`T`を構築して所有する。そうでなければ`**this = std::forward(u)`と等価。 + + +## 戻り値 +`*this`への参照。 + + +## 例外 +- (1) : 強い例外安全性を保証する。例外が送出された場合、[`this->valueless_after_move()`](valueless_after_move.md)の結果は変化しない。 +- (2) : 以下と等価な`noexcept`指定を持つ: +```cpp +noexcept(allocator_traits::propagate_on_container_move_assignment::value || + allocator_traits::is_always_equal::value) +``` +* allocator_traits[link /reference/memory/allocator_traits.md] + + +## 例 +```cpp example +#include +#include + +int main() +{ + std::indirect a{1}; + std::indirect b{2}; + + a = b; // (1) コピー代入(ディープコピー) + assert(*a == 2); + *a = 3; + assert(*b == 2); // bは影響を受けない + + a = 10; // (3) 値の代入 + assert(*a == 10); + + a = std::move(b); // (2) ムーブ代入 + assert(*a == 2); + assert(b.valueless_after_move()); +} +``` +* std::indirect[color ff0000] +* std::move[link /reference/utility/move.md] +* valueless_after_move[link valueless_after_move.md] + +### 出力 +``` +``` + + +## バージョン +### 言語 +- C++26 + +### 処理系 +- [Clang](/implementation.md#clang): 22 [mark noimpl] +- [GCC](/implementation.md#gcc): 16.1 [mark verified] +- [Visual C++](/implementation.md#visual_cpp): 2026 Update 2 [mark noimpl] + + +## 関連項目 +- [`std::indirect`](../indirect.md) + + +## 参照 +- [P3019R14 `indirect` and `polymorphic`: Vocabulary Types for Composite Class Design](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3019r14.pdf) diff --git a/reference/memory/indirect/op_compare_3way.md b/reference/memory/indirect/op_compare_3way.md new file mode 100644 index 0000000000..021ff8c0d0 --- /dev/null +++ b/reference/memory/indirect/op_compare_3way.md @@ -0,0 +1,72 @@ +# operator<=> +* memory[meta header] +* std[meta namespace] +* indirect[meta class] +* function[meta id-type] +* cpp26[meta cpp] + +```cpp +template +friend constexpr auto operator<=>( + const indirect& lhs, const indirect& rhs) + -> synth-three-way-result; // (1) + +template +friend constexpr auto operator<=>( + const indirect& lhs, const U& rhs) + -> synth-three-way-result; // (2) +``` + +## 概要 +- (1) : 2つの`indirect`オブジェクトが所有する値を三方比較する。 +- (2) : `indirect`オブジェクトが所有する値と、別の値`rhs`を三方比較する。 + +いずれも*Hidden friends*として定義される。 + + +## 戻り値 +- (1) : `lhs`と`rhs`のいずれかが無効値状態であれば`!lhs.valueless_after_move() <=> !rhs.valueless_after_move()`、そうでなければ`synth-three-way(*lhs, *rhs)`。 +- (2) : `lhs`が無効値状態であれば[`std::strong_ordering::less`](/reference/compare/strong_ordering.md)、そうでなければ`synth-three-way(*lhs, rhs)`。 + + +## 備考 +この演算子により、`operator<` / `operator<=` / `operator>` / `operator>=`が使用可能になる。 + + +## 例 +```cpp example +#include +#include + +int main() +{ + std::indirect a{1}; + std::indirect b{2}; + assert(a < b); // (1) indirect同士の比較 + assert((a <=> b) < 0); + assert(a < 2); // (2) 値との比較 +} +``` +* std::indirect[color ff0000] + +### 出力 +``` +``` + + +## バージョン +### 言語 +- C++26 + +### 処理系 +- [Clang](/implementation.md#clang): 22 [mark noimpl] +- [GCC](/implementation.md#gcc): 16.1 [mark verified] +- [Visual C++](/implementation.md#visual_cpp): 2026 Update 2 [mark noimpl] + + +## 関連項目 +- [`std::indirect`](../indirect.md) + + +## 参照 +- [P3019R14 `indirect` and `polymorphic`: Vocabulary Types for Composite Class Design](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3019r14.pdf) diff --git a/reference/memory/indirect/op_constructor.md b/reference/memory/indirect/op_constructor.md new file mode 100644 index 0000000000..756c50dc81 --- /dev/null +++ b/reference/memory/indirect/op_constructor.md @@ -0,0 +1,156 @@ +# コンストラクタ +* memory[meta header] +* std[meta namespace] +* indirect[meta class] +* function[meta id-type] +* cpp26[meta cpp] + +```cpp +explicit constexpr + indirect(); // (1) + +explicit constexpr + indirect(allocator_arg_t, + const Allocator& a); // (2) + +constexpr + indirect(const indirect& other); // (3) + +constexpr + indirect(allocator_arg_t, + const Allocator& a, + const indirect& other); // (4) + +constexpr + indirect(indirect&& other) noexcept; // (5) + +constexpr + indirect(allocator_arg_t, + const Allocator& a, + indirect&& other) noexcept(see below); // (6) + +template +explicit constexpr + indirect(U&& u); // (7) + +template +explicit constexpr + indirect(allocator_arg_t, + const Allocator& a, U&& u); // (8) + +template +explicit constexpr + indirect(in_place_t, + Us&&... us); // (9) + +template +explicit constexpr + indirect(allocator_arg_t, + const Allocator& a, + in_place_t, + Us&&... us); // (10) + +template +explicit constexpr + indirect(in_place_t, + initializer_list ilist, + Us&&... us); // (11) + +template +explicit constexpr + indirect(allocator_arg_t, + const Allocator& a, + in_place_t, + initializer_list ilist, + Us&&... us); // (12) +``` +* allocator_arg_t[link /reference/memory/allocator_arg_t.md] +* in_place_t[link /reference/utility/in_place_t.md] +* initializer_list[link /reference/initializer_list/initializer_list.md] + +## 概要 +`indirect`オブジェクトを構築する。`allocator_arg_t`を第1引数に取るオーバーロードは、使用するアロケータ`a`を明示的に指定する。 + +- (1), (2) : デフォルトコンストラクタ。`T`をデフォルト構築して所有する。 +- (3), (4) : コピーコンストラクタ。`other`が所有するオブジェクトをディープコピーして所有する。`other`が無効値状態の場合、構築されるオブジェクトも無効値状態となる。 +- (5), (6) : ムーブコンストラクタ。`other`が所有するオブジェクトの所有権を移す。ムーブ後の`other`は無効値状態となる。 +- (7), (8) : 単一の引数`u`から`T`を構築して所有する。 +- (9), (10) : `in_place_t`をマーカーとして、引数`us...`から`T`を直接構築して所有する。 +- (11), (12) : `in_place_t`をマーカーとして、初期化子リストと引数`us...`から`T`を直接構築して所有する。 + + +## テンプレートパラメータ制約 +- (7), (8) : [`remove_cvref_t`](/reference/type_traits/remove_cvref.md)``が`indirect`でも`in_place_t`でもなく、かつ[`is_constructible_v`](/reference/type_traits/is_constructible.md)``が`true`であること。(7)はさらに[`is_default_constructible_v`](/reference/type_traits/is_default_constructible.md)``が`true`であること。 +- (9), (10) : [`is_constructible_v`](/reference/type_traits/is_constructible.md)``が`true`であること。(9)はさらに[`is_default_constructible_v`](/reference/type_traits/is_default_constructible.md)``が`true`であること。 +- (11), (12) : [`is_constructible_v`](/reference/type_traits/is_constructible.md)`&, Us...>`が`true`であること。(11)はさらに[`is_default_constructible_v`](/reference/type_traits/is_default_constructible.md)``が`true`であること。 + + +## 適格要件 +- (1), (2) : [`is_default_constructible_v`](/reference/type_traits/is_default_constructible.md)``が`true`であること。 +- (3), (4) : [`is_copy_constructible_v`](/reference/type_traits/is_copy_constructible.md)``が`true`であること。 +- (6) : [`allocator_traits`](/reference/memory/allocator_traits.md)`::is_always_equal::value`が`false`の場合、`T`が完全型であること。 + + +## 例外 +- すべてのオーバーロード : [`allocator_traits`](/reference/memory/allocator_traits.md)`::allocate()`または[`allocator_traits`](/reference/memory/allocator_traits.md)`::construct()`が例外を送出した場合を除いて、例外を送出しない。 +- (6) : 以下と等価な`noexcept`指定を持つ: +```cpp +noexcept(allocator_traits::is_always_equal::value) +``` +* allocator_traits[link /reference/memory/allocator_traits.md] + + +## 事後条件 +- (5), (6) : `other`は無効値状態となる。 + + +## 例 +```cpp example +#include +#include +#include +#include + +int main() +{ + std::indirect a; // (1) デフォルト構築 + assert(*a == 0); + + std::indirect b{42}; // (7) 単一の引数から構築 + assert(*b == 42); + + std::indirect c{std::in_place, 3, 'x'}; // (9) in_placeで直接構築 + assert(*c == "xxx"); + + std::indirect d = b; // (3) コピー構築(ディープコピー) + assert(*d == 42); + + std::indirect e = std::move(d); // (5) ムーブ構築 + assert(*e == 42); + assert(d.valueless_after_move()); // ムーブ後は無効値状態 +} +``` +* std::indirect[color ff0000] +* std::in_place[link /reference/utility/in_place_t.md] + +### 出力 +``` +``` + + +## バージョン +### 言語 +- C++26 + +### 処理系 +- [Clang](/implementation.md#clang): 22 [mark noimpl] +- [GCC](/implementation.md#gcc): 16.1 [mark verified] +- [Visual C++](/implementation.md#visual_cpp): 2026 Update 2 [mark noimpl] + + +## 関連項目 +- [`std::indirect`](../indirect.md) + + +## 参照 +- [P3019R14 `indirect` and `polymorphic`: Vocabulary Types for Composite Class Design](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3019r14.pdf) diff --git a/reference/memory/indirect/op_deduction_guide.md b/reference/memory/indirect/op_deduction_guide.md new file mode 100644 index 0000000000..e1544a47b5 --- /dev/null +++ b/reference/memory/indirect/op_deduction_guide.md @@ -0,0 +1,59 @@ +# 推論補助 +* memory[meta header] +* std[meta namespace] +* indirect[meta class] +* function[meta id-type] +* cpp26[meta cpp] + +```cpp +template +indirect(Value) -> indirect; // (1) + +template +indirect(allocator_arg_t, Allocator, Value) + -> indirect::template rebind_alloc>; // (2) +``` +* allocator_arg_t[link /reference/memory/allocator_arg_t.md] + +## 概要 +`std::indirect`クラステンプレートの型推論を補助する。 + +- (1) : 単一の値から`indirect`を構築する場合、その値の型を`T`として推論する。 +- (2) : アロケータと値から構築する場合、値の型を`T`とし、アロケータを`Value`向けに`rebind`した型を`Allocator`として推論する。 + + +## 例 +```cpp example +#include +#include + +int main() +{ + std::indirect a{42}; + static_assert(std::is_same_v>); +} +``` +* std::indirect[color ff0000] + +### 出力 +``` +``` + + +## バージョン +### 言語 +- C++26 + +### 処理系 +- [Clang](/implementation.md#clang): 22 [mark noimpl] +- [GCC](/implementation.md#gcc): 16.1 [mark verified] +- [Visual C++](/implementation.md#visual_cpp): 2026 Update 2 [mark noimpl] + + +## 関連項目 +- [`std::indirect`](../indirect.md) + + +## 参照 +- [P3019R14 `indirect` and `polymorphic`: Vocabulary Types for Composite Class Design](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3019r14.pdf) diff --git a/reference/memory/indirect/op_deref.md b/reference/memory/indirect/op_deref.md new file mode 100644 index 0000000000..ef08fcf8ac --- /dev/null +++ b/reference/memory/indirect/op_deref.md @@ -0,0 +1,72 @@ +# operator* +* memory[meta header] +* std[meta namespace] +* indirect[meta class] +* function[meta id-type] +* cpp26[meta cpp] + +```cpp +constexpr const T& operator*() const & noexcept; // (1) +constexpr T& operator*() & noexcept; // (2) +constexpr const T&& operator*() const && noexcept; // (3) +constexpr T&& operator*() && noexcept; // (4) +``` + +## 概要 +所有するオブジェクトへの参照を取得する。`const`なアクセス経路では`const`が所有オブジェクトに伝播する。 + + +## 事前条件 +`*this`が無効値状態でないこと。 + + +## 戻り値 +- (1), (2) : 所有するオブジェクトへの参照。 +- (3), (4) : 所有するオブジェクトへの右辺値参照(`std::move(*p)`)。 + + +## 例外 +投げない。 + + +## 例 +```cpp example +#include +#include +#include + +int main() +{ + std::indirect a{42}; + assert(*a == 42); // 参照の取得 + *a = 10; // 非const版で書き換え + assert(*a == 10); + + // constなアクセス経路ではconstが伝播する + const std::indirect b{5}; + static_assert(std::is_same_v); +} +``` +* std::indirect[color ff0000] + +### 出力 +``` +``` + + +## バージョン +### 言語 +- C++26 + +### 処理系 +- [Clang](/implementation.md#clang): 22 [mark noimpl] +- [GCC](/implementation.md#gcc): 16.1 [mark verified] +- [Visual C++](/implementation.md#visual_cpp): 2026 Update 2 [mark noimpl] + + +## 関連項目 +- [`std::indirect`](../indirect.md) + + +## 参照 +- [P3019R14 `indirect` and `polymorphic`: Vocabulary Types for Composite Class Design](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3019r14.pdf) diff --git a/reference/memory/indirect/op_destructor.md b/reference/memory/indirect/op_destructor.md new file mode 100644 index 0000000000..4769f76243 --- /dev/null +++ b/reference/memory/indirect/op_destructor.md @@ -0,0 +1,39 @@ +# デストラクタ +* memory[meta header] +* std[meta namespace] +* indirect[meta class] +* function[meta id-type] +* cpp26[meta cpp] + +```cpp +constexpr ~indirect(); +``` + +## 概要 +`indirect`オブジェクトを破棄する。 + + +## 適格要件 +`T`は完全型であること。 + + +## 効果 +`*this`が無効値状態でなければ、所有するオブジェクトを[`allocator_traits`](/reference/memory/allocator_traits.md)`::destroy`で破棄し、ストレージを解放する。 + + +## バージョン +### 言語 +- C++26 + +### 処理系 +- [Clang](/implementation.md#clang): 22 [mark noimpl] +- [GCC](/implementation.md#gcc): 16.1 [mark verified] +- [Visual C++](/implementation.md#visual_cpp): 2026 Update 2 [mark noimpl] + + +## 関連項目 +- [`std::indirect`](../indirect.md) + + +## 参照 +- [P3019R14 `indirect` and `polymorphic`: Vocabulary Types for Composite Class Design](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3019r14.pdf) diff --git a/reference/memory/indirect/op_equal.md b/reference/memory/indirect/op_equal.md new file mode 100644 index 0000000000..91417707f0 --- /dev/null +++ b/reference/memory/indirect/op_equal.md @@ -0,0 +1,75 @@ +# operator== +* memory[meta header] +* std[meta namespace] +* indirect[meta class] +* function[meta id-type] +* cpp26[meta cpp] + +```cpp +template +friend constexpr bool operator==( + const indirect& lhs, const indirect& rhs) noexcept(see below); // (1) + +template +friend constexpr bool operator==( + const indirect& lhs, const U& rhs) noexcept(see below); // (2) +``` + +## 概要 +- (1) : 2つの`indirect`オブジェクトが所有する値を等値比較する。 +- (2) : `indirect`オブジェクトが所有する値と、別の値`rhs`を等値比較する。 + +いずれも*Hidden friends*として定義される。 + + +## 適格要件 +- (1) : 式`*lhs == *rhs`が適格であり、その結果が`bool`に変換可能であること。 +- (2) : 式`*lhs == rhs`が適格であり、その結果が`bool`に変換可能であること。 + + +## 戻り値 +- (1) : `lhs`と`rhs`のいずれかが無効値状態であれば`lhs.valueless_after_move() == rhs.valueless_after_move()`、そうでなければ`*lhs == *rhs`。 +- (2) : `lhs`が無効値状態であれば`false`、そうでなければ`*lhs == rhs`。 + + +## 備考 +この演算子により、`operator!=`が使用可能になる。 + + +## 例 +```cpp example +#include +#include + +int main() +{ + std::indirect a{42}; + std::indirect b{42}; + assert(a == b); // (1) indirect同士の比較 + assert(a == 42); // (2) 値との比較 + assert(a != 0); +} +``` +* std::indirect[color ff0000] + +### 出力 +``` +``` + + +## バージョン +### 言語 +- C++26 + +### 処理系 +- [Clang](/implementation.md#clang): 22 [mark noimpl] +- [GCC](/implementation.md#gcc): 16.1 [mark verified] +- [Visual C++](/implementation.md#visual_cpp): 2026 Update 2 [mark noimpl] + + +## 関連項目 +- [`std::indirect`](../indirect.md) + + +## 参照 +- [P3019R14 `indirect` and `polymorphic`: Vocabulary Types for Composite Class Design](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3019r14.pdf) diff --git a/reference/memory/indirect/swap.md b/reference/memory/indirect/swap.md new file mode 100644 index 0000000000..f482501997 --- /dev/null +++ b/reference/memory/indirect/swap.md @@ -0,0 +1,69 @@ +# swap +* memory[meta header] +* std[meta namespace] +* indirect[meta class] +* function[meta id-type] +* cpp26[meta cpp] + +```cpp +constexpr void swap(indirect& other) noexcept(see below); +``` + +## 概要 +`*this`と`other`の状態を交換する。所有オブジェクトまたは無効値状態を交換する。 + + +## 事前条件 +[`allocator_traits`](/reference/memory/allocator_traits.md)`::propagate_on_container_swap::value`が`true`の場合、`Allocator`はCpp17Swappable要件を満たすこと。そうでない場合、`get_allocator() == other.get_allocator()`が`true`であること。 + + +## 効果 +`*this`と`other`の状態(所有オブジェクトまたは無効値状態)を交換する。`propagate_on_container_swap::value`が`true`の場合はアロケータも交換する。所有オブジェクトに対して直接`swap`を呼ぶわけではない。 + + +## 例外 +以下と等価な`noexcept`指定を持つ: + +```cpp +noexcept(allocator_traits::propagate_on_container_swap::value || + allocator_traits::is_always_equal::value) +``` +* allocator_traits[link /reference/memory/allocator_traits.md] + + +## 例 +```cpp example +#include +#include + +int main() +{ + std::indirect a{1}; + std::indirect b{2}; + a.swap(b); + assert(*a == 2 && *b == 1); +} +``` +* std::indirect[color ff0000] + +### 出力 +``` +``` + + +## バージョン +### 言語 +- C++26 + +### 処理系 +- [Clang](/implementation.md#clang): 22 [mark noimpl] +- [GCC](/implementation.md#gcc): 16.1 [mark verified] +- [Visual C++](/implementation.md#visual_cpp): 2026 Update 2 [mark noimpl] + + +## 関連項目 +- [`std::indirect`](../indirect.md) + + +## 参照 +- [P3019R14 `indirect` and `polymorphic`: Vocabulary Types for Composite Class Design](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3019r14.pdf) diff --git a/reference/memory/indirect/swap_free.md b/reference/memory/indirect/swap_free.md new file mode 100644 index 0000000000..b85df0bd72 --- /dev/null +++ b/reference/memory/indirect/swap_free.md @@ -0,0 +1,63 @@ +# swap +* memory[meta header] +* std[meta namespace] +* indirect[meta class] +* function[meta id-type] +* cpp26[meta cpp] + +```cpp +friend constexpr void swap(indirect& lhs, indirect& rhs) noexcept(see below); +``` + +## 概要 +2つの`indirect`オブジェクトを交換する。*Hidden friends*として定義される。 + + +## 効果 +`lhs.swap(rhs)`と等価。 + + +## 例外 +以下と等価な`noexcept`指定を持つ: + +```cpp +noexcept(noexcept(lhs.swap(rhs))) +``` + + +## 例 +```cpp example +#include +#include + +int main() +{ + std::indirect a{1}; + std::indirect b{2}; + swap(a, b); // ADLにより非メンバswapが呼ばれる + assert(*a == 2 && *b == 1); +} +``` +* std::indirect[color ff0000] + +### 出力 +``` +``` + + +## バージョン +### 言語 +- C++26 + +### 処理系 +- [Clang](/implementation.md#clang): 22 [mark noimpl] +- [GCC](/implementation.md#gcc): 16.1 [mark verified] +- [Visual C++](/implementation.md#visual_cpp): 2026 Update 2 [mark noimpl] + + +## 関連項目 +- [`std::indirect`](../indirect.md) + + +## 参照 +- [P3019R14 `indirect` and `polymorphic`: Vocabulary Types for Composite Class Design](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3019r14.pdf) diff --git a/reference/memory/indirect/valueless_after_move.md b/reference/memory/indirect/valueless_after_move.md new file mode 100644 index 0000000000..f866a5a8e5 --- /dev/null +++ b/reference/memory/indirect/valueless_after_move.md @@ -0,0 +1,61 @@ +# valueless_after_move +* memory[meta header] +* std[meta namespace] +* indirect[meta class] +* function[meta id-type] +* cpp26[meta cpp] + +```cpp +constexpr bool valueless_after_move() const noexcept; +``` + +## 概要 +`*this`が無効値状態かどうかを判定する。`indirect`はムーブされたあとにのみ無効値状態となりうる。 + + +## 戻り値 +`*this`が無効値状態であれば`true`、そうでなければ`false`。 + + +## 例外 +投げない。 + + +## 例 +```cpp example +#include +#include + +int main() +{ + std::indirect a{42}; + assert(!a.valueless_after_move()); + + std::indirect b = std::move(a); + assert(a.valueless_after_move()); // ムーブ後は無効値状態 + assert(!b.valueless_after_move()); +} +``` +* std::indirect[color ff0000] + +### 出力 +``` +``` + + +## バージョン +### 言語 +- C++26 + +### 処理系 +- [Clang](/implementation.md#clang): 22 [mark noimpl] +- [GCC](/implementation.md#gcc): 16.1 [mark verified] +- [Visual C++](/implementation.md#visual_cpp): 2026 Update 2 [mark noimpl] + + +## 関連項目 +- [`std::indirect`](../indirect.md) + + +## 参照 +- [P3019R14 `indirect` and `polymorphic`: Vocabulary Types for Composite Class Design](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3019r14.pdf) diff --git a/reference/memory/polymorphic.md b/reference/memory/polymorphic.md new file mode 100644 index 0000000000..ad7a74aed6 --- /dev/null +++ b/reference/memory/polymorphic.md @@ -0,0 +1,147 @@ +# polymorphic +* memory[meta header] +* std[meta namespace] +* class template[meta id-type] +* cpp26[meta cpp] + +```cpp +namespace std { + template > + class polymorphic; + + namespace pmr { + template + using polymorphic = std::polymorphic>; + } +} +``` +* allocator[link allocator.md] +* polymorphic_allocator[link /reference/memory_resource/polymorphic_allocator.md] + +## 概要 +`std::polymorphic`クラスは、動的確保したオブジェクトに値の意味論をもたせつつ、`T`から派生した任意の型のオブジェクトを多態的に保持できる型である。 + +[`std::indirect`](indirect.md)クラスが単一の型`T`のオブジェクトを保持するのに対し、`std::polymorphic`クラスは`T`を基底とする派生型のオブジェクトを保持できる。値型としての性質は`std::indirect`クラスと共通している: + +- ディープコピー: `std::polymorphic`クラスのオブジェクトをコピーすると、実際に保持している派生型のオブジェクトが、その派生型のコピーコンストラクタによって複製される(型消去をとおした仮想ディスパッチが用いられる) +- `const`の伝播: `const`なアクセス経路から所有オブジェクトにアクセスすると、所有オブジェクトにも`const`が伝播する +- 不完全型のサポート: テンプレートパラメータ`T`は不完全型でもよい + +これらの性質によって、`std::polymorphic`クラスは多態的な性質をもつクラスのメンバ変数として適しており、コンパイラによる特殊メンバ関数の自動生成と協調して動作する。 + +所有オブジェクトを持たない状態を「無効値状態 (valueless state)」と呼ぶ。`std::polymorphic`クラスが無効値状態になるのは、ムーブ後に空となった場合のみである。無効値状態のオブジェクトに対する`operator*`や`operator->`の呼び出しは未定義動作を引き起こす。無効値状態かどうかは[`valueless_after_move()`](polymorphic/valueless_after_move.md)で判定できる。 + +保持する型の集合が既知である場合は、[`std::variant`](/reference/variant/variant.md)や`indirect>`の使用を検討するとよい。 + + +## テンプレートパラメータ制約 +- `Allocator`はCpp17Allocator要件を満たすこと。 +- [`allocator_traits`](/reference/memory/allocator_traits.md)`::value_type`が`T`と同じ型であること + + +## 適格要件 +- 以下のいずれかの場合に、プログラムは不適格となる + - `T`がオブジェクト型でない + - 配列型である + - (CV修飾された) [`std::in_place_t`](/reference/utility/in_place_t.md)である + - (CV修飾された) [`std::in_place_type_t`](/reference/utility/in_place_type_t.md)の特殊化である + - CV修飾された型である +- `std::polymorphic`の明示的特殊化・部分特殊化をユーザーが宣言した場合、動作は未定義である + + +## メンバ関数 +### 構築・破棄 + +| 名前 | 説明 | 対応バージョン | +|------|------|----------------| +| [`(constructor)`](polymorphic/op_constructor.md) | コンストラクタ | C++26 | +| [`(destructor)`](polymorphic/op_destructor.md) | デストラクタ | C++26 | +| [`operator=`](polymorphic/op_assign.md) | 代入演算子 | C++26 | + +### 値へのアクセス + +| 名前 | 説明 | 対応バージョン | +|------|------|----------------| +| [`operator*`](polymorphic/op_deref.md) | 所有するオブジェクトへの参照を取得する | C++26 | +| [`operator->`](polymorphic/op_arrow.md) | 所有するオブジェクトのメンバへアクセスする | C++26 | +| [`valueless_after_move`](polymorphic/valueless_after_move.md) | 無効値状態かどうかを判定する | C++26 | + +### その他 + +| 名前 | 説明 | 対応バージョン | +|------|------|----------------| +| [`get_allocator`](polymorphic/get_allocator.md) | アロケータを取得する | C++26 | +| [`swap`](polymorphic/swap.md) | 他の`polymorphic`オブジェクトと値を交換する | C++26 | + + +## メンバ型 + +| 名前 | 定義 | 対応バージョン | +|------|------|----------------| +| `value_type` | `T` | C++26 | +| `allocator_type` | `Allocator` | C++26 | +| `pointer` | [`allocator_traits`](/reference/memory/allocator_traits.md)`::pointer` | C++26 | +| `const_pointer` | [`allocator_traits`](/reference/memory/allocator_traits.md)`::const_pointer` | C++26 | + + +## 非メンバ(*Hidden friends*)関数 + +| 名前 | 説明 | 対応バージョン | +|------|------|----------------| +| [`swap`](polymorphic/swap_free.md) | 2つの`polymorphic`オブジェクトを交換する | C++26 | + + +## 例 +```cpp example +#include +#include + +struct Shape { + virtual ~Shape() = default; + virtual int area() const = 0; +}; + +struct Square : Shape { + int side; + Square(int s) : side(s) {} + int area() const override { return side * side; } +}; + +int main() +{ + // Shapeから派生したSquareを、値の意味論で多態的に保持する + std::polymorphic a{std::in_place_type, 3}; + assert(a->area() == 9); + + // コピーは派生型(Square)のディープコピー + std::polymorphic b = a; + assert(b->area() == 9); +} +``` +* std::polymorphic[color ff0000] +* std::in_place_type[link /reference/utility/in_place_type_t.md] + +### 出力 +``` +``` + + +## バージョン +### 言語 +- C++26 + +### 処理系 +- [Clang](/implementation.md#clang): 22 [mark noimpl] +- [GCC](/implementation.md#gcc): 16.1 [mark verified] +- [Visual C++](/implementation.md#visual_cpp): 2026 Update 2 [mark noimpl] + + +## 関連項目 +- [`std::indirect`](indirect.md) 単一の型を保持する値型 +- [`std::variant`](/reference/variant/variant.md) 既知の型集合から1つを保持する型 +- [`std::unique_ptr`](unique_ptr.md) 多態的な所有権をもつが参照の意味論をもつスマートポインタ + + +## 参照 +- [P3019R14 `indirect` and `polymorphic`: Vocabulary Types for Composite Class Design](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3019r14.pdf) + - C++26で`indirect`と`polymorphic`が追加された diff --git a/reference/memory/polymorphic/get_allocator.md b/reference/memory/polymorphic/get_allocator.md new file mode 100644 index 0000000000..c7981d7a06 --- /dev/null +++ b/reference/memory/polymorphic/get_allocator.md @@ -0,0 +1,39 @@ +# get_allocator +* memory[meta header] +* std[meta namespace] +* polymorphic[meta class] +* function[meta id-type] +* cpp26[meta cpp] + +```cpp +constexpr allocator_type get_allocator() const noexcept; +``` + +## 概要 +このオブジェクトが使用するアロケータを取得する。 + + +## 戻り値 +所有するアロケータのコピー。 + + +## 例外 +投げない。 + + +## バージョン +### 言語 +- C++26 + +### 処理系 +- [Clang](/implementation.md#clang): 22 [mark noimpl] +- [GCC](/implementation.md#gcc): 16.1 [mark verified] +- [Visual C++](/implementation.md#visual_cpp): 2026 Update 2 [mark noimpl] + + +## 関連項目 +- [`std::polymorphic`](../polymorphic.md) + + +## 参照 +- [P3019R14 `indirect` and `polymorphic`: Vocabulary Types for Composite Class Design](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3019r14.pdf) diff --git a/reference/memory/polymorphic/op_arrow.md b/reference/memory/polymorphic/op_arrow.md new file mode 100644 index 0000000000..fad8e5e627 --- /dev/null +++ b/reference/memory/polymorphic/op_arrow.md @@ -0,0 +1,74 @@ +# operator-> +* memory[meta header] +* std[meta namespace] +* polymorphic[meta class] +* function[meta id-type] +* cpp26[meta cpp] + +```cpp +constexpr const_pointer operator->() const noexcept; // (1) +constexpr pointer operator->() noexcept; // (2) +``` + +## 概要 +所有するオブジェクトのメンバへ、基底型`T`としてアクセスするためのポインタを取得する。 + + +## 事前条件 +`*this`が無効値状態でないこと。 + + +## 戻り値 +所有するオブジェクトを指すポインタ。 + + +## 例外 +投げない。 + + +## 例 +```cpp example +#include +#include + +struct Base { + virtual ~Base() = default; + virtual int f() const { return 0; } +}; +struct Derived : Base { + int x = 42; + Derived() = default; + Derived(int x) : x(x) {} + int f() const override { return x; } +}; + +int main() +{ + std::polymorphic a{std::in_place_type}; + assert(a->f() == 42); // 基底型Baseのメンバへアクセス(仮想ディスパッチ) +} +``` +* std::polymorphic[color ff0000] +* std::in_place_type[link /reference/utility/in_place_type_t.md] + +### 出力 +``` +``` + + +## バージョン +### 言語 +- C++26 + +### 処理系 +- [Clang](/implementation.md#clang): 22 [mark noimpl] +- [GCC](/implementation.md#gcc): 16.1 [mark verified] +- [Visual C++](/implementation.md#visual_cpp): 2026 Update 2 [mark noimpl] + + +## 関連項目 +- [`std::polymorphic`](../polymorphic.md) + + +## 参照 +- [P3019R14 `indirect` and `polymorphic`: Vocabulary Types for Composite Class Design](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3019r14.pdf) diff --git a/reference/memory/polymorphic/op_assign.md b/reference/memory/polymorphic/op_assign.md new file mode 100644 index 0000000000..0e472b1660 --- /dev/null +++ b/reference/memory/polymorphic/op_assign.md @@ -0,0 +1,93 @@ +# 代入演算子 +* memory[meta header] +* std[meta namespace] +* polymorphic[meta class] +* function[meta id-type] +* cpp26[meta cpp] + +```cpp +constexpr polymorphic& operator=(const polymorphic& other); // (1) +constexpr polymorphic& operator=(polymorphic&& other) noexcept(see below); // (2) +``` + +## 概要 +- (1) : コピー代入。`other`が保持する派生型のオブジェクトをディープコピーする。 +- (2) : ムーブ代入。`other`から所有権を移す。 + + +## 適格要件 +- (1) : `T`は完全型であること。 + + +## 効果 +- (1) : `addressof(other) == this`であれば何もしない。そうでなければ、アロケータの伝播規則に従い、`other`が保持するオブジェクトのコピーを`*this`がもつようにする。`other`が無効値状態であれば`*this`も無効値状態にする。 +- (2) : `addressof(other) == this`であれば何もしない。そうでなければ、アロケータの伝播規則に従い、`other`から所有権を移すか、ムーブ構築する。 + + +## 戻り値 +`*this`への参照。 + + +## 例外 +- (1) : 強い例外安全性を保証する。例外が送出された場合、`*this`や`other`に影響はない。 +- (2) : 以下と等価な`noexcept`指定を持つ: + +```cpp +noexcept(allocator_traits::propagate_on_container_move_assignment::value || + allocator_traits::is_always_equal::value) +``` +* allocator_traits[link /reference/memory/allocator_traits.md] + + +## 例 +```cpp example +#include +#include + +struct Base { + virtual ~Base() = default; + virtual int f() const { return 0; } +}; +struct Derived : Base { + int x = 42; + Derived() = default; + Derived(int x) : x(x) {} + int f() const override { return x; } +}; + +int main() +{ + std::polymorphic a{std::in_place_type, 1}; + std::polymorphic b{std::in_place_type, 2}; + + a = b; // (1) コピー代入(派生型のディープコピー) + assert(a->f() == 2); + + a = std::move(b); // (2) ムーブ代入 + assert(a->f() == 2); +} +``` +* std::polymorphic[color ff0000] +* std::in_place_type[link /reference/utility/in_place_type_t.md] + +### 出力 +``` +``` + + +## バージョン +### 言語 +- C++26 + +### 処理系 +- [Clang](/implementation.md#clang): 22 [mark noimpl] +- [GCC](/implementation.md#gcc): 16.1 [mark verified] +- [Visual C++](/implementation.md#visual_cpp): 2026 Update 2 [mark noimpl] + + +## 関連項目 +- [`std::polymorphic`](../polymorphic.md) + + +## 参照 +- [P3019R14 `indirect` and `polymorphic`: Vocabulary Types for Composite Class Design](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3019r14.pdf) diff --git a/reference/memory/polymorphic/op_constructor.md b/reference/memory/polymorphic/op_constructor.md new file mode 100644 index 0000000000..4a0e01af7c --- /dev/null +++ b/reference/memory/polymorphic/op_constructor.md @@ -0,0 +1,158 @@ +# コンストラクタ +* memory[meta header] +* std[meta namespace] +* polymorphic[meta class] +* function[meta id-type] +* cpp26[meta cpp] + +```cpp +explicit constexpr + polymorphic(); // (1) + +explicit constexpr + polymorphic(allocator_arg_t, + const Allocator& a); // (2) + +constexpr + polymorphic(const polymorphic& other); // (3) + +constexpr + polymorphic(allocator_arg_t, + const Allocator& a, + const polymorphic& other); // (4) + +constexpr + polymorphic(polymorphic&& other) noexcept; // (5) + +constexpr + polymorphic(allocator_arg_t, + const Allocator& a, + polymorphic&& other) noexcept(see below); // (6) + +template +explicit constexpr + polymorphic(U&& u); // (7) + +template +explicit constexpr + polymorphic(allocator_arg_t, + const Allocator& a, + U&& u); // (8) + +template +explicit constexpr + polymorphic(in_place_type_t, + Ts&&... ts); // (9) + +template +explicit constexpr + polymorphic(allocator_arg_t, + const Allocator& a, + in_place_type_t, Ts&&... ts); // (10) + +template +explicit constexpr + polymorphic(in_place_type_t, + initializer_list ilist, + Us&&... us); // (11) + +template +explicit constexpr + polymorphic(allocator_arg_t, const Allocator& a, + in_place_type_t, + initializer_list ilist, Us&&... us); // (12) +``` +* allocator_arg_t[link /reference/memory/allocator_arg_t.md] +* in_place_type_t[link /reference/utility/in_place_type_t.md] +* initializer_list[link /reference/initializer_list/initializer_list.md] + +## 概要 +`polymorphic`オブジェクトを構築する。`allocator_arg_t`を第1引数に取るオーバーロードは、使用するアロケータ`a`を明示的に指定する。 + +- (1), (2) : デフォルトコンストラクタ。`T`をデフォルト構築して所有する。 +- (3), (4) : コピーコンストラクタ。`other`が保持する派生型のオブジェクトをディープコピーして所有する。`other`が無効値状態の場合、構築されるオブジェクトも無効値状態となる。 +- (5), (6) : ムーブコンストラクタ。`other`が保持するオブジェクトの所有権を移す。 +- (7), (8) : 単一の引数`u`から、その型`U`(`T`から派生していてもよい)のオブジェクトを構築して所有する。 +- (9), (10) : `in_place_type_t`をマーカーとして、型`U`のオブジェクトを引数`ts...`から直接構築して所有する。 +- (11), (12) : `in_place_type_t`をマーカーとして、型`U`のオブジェクトを初期化子リストと引数`us...`から直接構築して所有する。 + + +## テンプレートパラメータ制約 +- (7), (8) : [`remove_cvref_t`](/reference/type_traits/remove_cvref.md)``を`UU`とするとき、`UU`が`polymorphic`でも`in_place_type_t`の特殊化でもなく、[`derived_from`](/reference/concepts/derived_from.md)``、[`is_constructible_v`](/reference/type_traits/is_constructible.md)``、[`is_copy_constructible_v`](/reference/type_traits/is_copy_constructible.md)``がいずれも`true`であること。(7)はさらに[`is_default_constructible_v`](/reference/type_traits/is_default_constructible.md)``が`true`であること。 +- (9), (10) : [`is_same_v`](/reference/type_traits/is_same.md)`<`[`remove_cvref_t`](/reference/type_traits/remove_cvref.md)`, U>`、[`derived_from`](/reference/concepts/derived_from.md)``、[`is_constructible_v`](/reference/type_traits/is_constructible.md)``、[`is_copy_constructible_v`](/reference/type_traits/is_copy_constructible.md)``がいずれも`true`であること。(9)はさらに[`is_default_constructible_v`](/reference/type_traits/is_default_constructible.md)``が`true`であること。 +- (11), (12) : [`is_same_v`](/reference/type_traits/is_same.md)`<`[`remove_cvref_t`](/reference/type_traits/remove_cvref.md)`, U>`、[`derived_from`](/reference/concepts/derived_from.md)``、[`is_constructible_v`](/reference/type_traits/is_constructible.md)`&, Us...>`、[`is_copy_constructible_v`](/reference/type_traits/is_copy_constructible.md)``がいずれも`true`であること。(11)はさらに[`is_default_constructible_v`](/reference/type_traits/is_default_constructible.md)``が`true`であること。 + + +## 適格要件 +- (1), (2) : [`is_default_constructible_v`](/reference/type_traits/is_default_constructible.md)``と[`is_copy_constructible_v`](/reference/type_traits/is_copy_constructible.md)``がともに`true`であること。 + + +## 効果 +所有するオブジェクトを、指定された型・引数とアロケータ`alloc`を用いて構築する。`allocator_arg_t`版は`alloc`を`a`で初期化する。 + + +## 例外 +- すべてのオーバーロード : [`allocator_traits`](/reference/memory/allocator_traits.md)`::allocate`または[`allocator_traits`](/reference/memory/allocator_traits.md)`::construct`が例外を送出した場合を除いて、例外を送出しない。 +- (6) : 以下と等価な`noexcept`指定を持つ: + +```cpp +noexcept(allocator_traits::is_always_equal::value) +``` +* allocator_traits[link /reference/memory/allocator_traits.md] + + +## 例 +```cpp example +#include +#include + +struct Base { + virtual ~Base() = default; + virtual int f() const { return 0; } +}; +struct Derived : Base { + int x = 42; + Derived() = default; + Derived(int x) : x(x) {} + int f() const override { return x; } +}; + +int main() +{ + // (9) in_place_typeで派生型Derivedを直接構築 + std::polymorphic a{std::in_place_type}; + assert(a->f() == 42); + + // (7) 派生型の値から構築 + std::polymorphic b{Derived{10}}; + assert(b->f() == 10); + + // (3) コピー構築(派生型Derivedのディープコピー) + std::polymorphic c = a; + assert(c->f() == 42); +} +``` +* std::polymorphic[color ff0000] +* std::in_place_type[link /reference/utility/in_place_type_t.md] + +### 出力 +``` +``` + + +## バージョン +### 言語 +- C++26 + +### 処理系 +- [Clang](/implementation.md#clang): 22 [mark noimpl] +- [GCC](/implementation.md#gcc): 16.1 [mark verified] +- [Visual C++](/implementation.md#visual_cpp): 2026 Update 2 [mark noimpl] + + +## 関連項目 +- [`std::polymorphic`](../polymorphic.md) + + +## 参照 +- [P3019R14 `indirect` and `polymorphic`: Vocabulary Types for Composite Class Design](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3019r14.pdf) diff --git a/reference/memory/polymorphic/op_deref.md b/reference/memory/polymorphic/op_deref.md new file mode 100644 index 0000000000..bfc03fe527 --- /dev/null +++ b/reference/memory/polymorphic/op_deref.md @@ -0,0 +1,75 @@ +# operator* +* memory[meta header] +* std[meta namespace] +* polymorphic[meta class] +* function[meta id-type] +* cpp26[meta cpp] + +```cpp +constexpr const T& operator*() const noexcept; // (1) +constexpr T& operator*() noexcept; // (2) +``` + +## 概要 +所有するオブジェクトへの、基底型`T`としての参照を取得する。`const`なアクセス経路では`const`が所有オブジェクトに伝播する。 + + +## 事前条件 +`*this`が無効値状態でないこと。 + + +## 戻り値 +所有するオブジェクトへの`T`型としての参照。 + + +## 例外 +投げない。 + + +## 例 +```cpp example +#include +#include + +struct Base { + virtual ~Base() = default; + virtual int f() const { return 0; } +}; +struct Derived : Base { + int x = 42; + Derived() = default; + Derived(int x) : x(x) {} + int f() const override { return x; } +}; + +int main() +{ + std::polymorphic a{std::in_place_type}; + Base& r = *a; // 基底型Baseとしての参照を取得 + assert(r.f() == 42); // 仮想関数で派生型Derivedの実装が呼ばれる +} +``` +* std::polymorphic[color ff0000] +* std::in_place_type[link /reference/utility/in_place_type_t.md] + +### 出力 +``` +``` + + +## バージョン +### 言語 +- C++26 + +### 処理系 +- [Clang](/implementation.md#clang): 22 [mark noimpl] +- [GCC](/implementation.md#gcc): 16.1 [mark verified] +- [Visual C++](/implementation.md#visual_cpp): 2026 Update 2 [mark noimpl] + + +## 関連項目 +- [`std::polymorphic`](../polymorphic.md) + + +## 参照 +- [P3019R14 `indirect` and `polymorphic`: Vocabulary Types for Composite Class Design](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3019r14.pdf) diff --git a/reference/memory/polymorphic/op_destructor.md b/reference/memory/polymorphic/op_destructor.md new file mode 100644 index 0000000000..94fba45470 --- /dev/null +++ b/reference/memory/polymorphic/op_destructor.md @@ -0,0 +1,39 @@ +# デストラクタ +* memory[meta header] +* std[meta namespace] +* polymorphic[meta class] +* function[meta id-type] +* cpp26[meta cpp] + +```cpp +constexpr ~polymorphic(); +``` + +## 概要 +`polymorphic`オブジェクトを破棄する。 + + +## 適格要件 +`T`は完全型であること。 + + +## 効果 +`*this`が無効値状態でなければ、所有するオブジェクトを[`allocator_traits`](/reference/memory/allocator_traits.md)`::destroy`で破棄し、ストレージを解放する。 + + +## バージョン +### 言語 +- C++26 + +### 処理系 +- [Clang](/implementation.md#clang): 22 [mark noimpl] +- [GCC](/implementation.md#gcc): 16.1 [mark verified] +- [Visual C++](/implementation.md#visual_cpp): 2026 Update 2 [mark noimpl] + + +## 関連項目 +- [`std::polymorphic`](../polymorphic.md) + + +## 参照 +- [P3019R14 `indirect` and `polymorphic`: Vocabulary Types for Composite Class Design](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3019r14.pdf) diff --git a/reference/memory/polymorphic/swap.md b/reference/memory/polymorphic/swap.md new file mode 100644 index 0000000000..695d15cceb --- /dev/null +++ b/reference/memory/polymorphic/swap.md @@ -0,0 +1,74 @@ +# swap +* memory[meta header] +* std[meta namespace] +* polymorphic[meta class] +* function[meta id-type] +* cpp26[meta cpp] + +```cpp +constexpr void swap(polymorphic& other) noexcept(see below); +``` + +## 概要 +`*this`と`other`の状態を交換する。所有オブジェクトまたは無効値状態を交換する。 + + +## 事前条件 +[`allocator_traits`](/reference/memory/allocator_traits.md)`::propagate_on_container_swap::value`が`true`の場合、`Allocator`は*Cpp17Swappable*要件を満たすこと。そうでない場合、`get_allocator() == other.get_allocator()`が`true`であること。 + + +## 効果 +`*this`と`other`の状態を交換する。`propagate_on_container_swap::value`が`true`の場合はアロケータも交換する。 + + +## 例外 +以下と等価な`noexcept`指定を持つ: + +```cpp +noexcept(allocator_traits::propagate_on_container_swap::value || + allocator_traits::is_always_equal::value) +``` +* allocator_traits[link /reference/memory/allocator_traits.md] + + +## 例 +```cpp example +#include +#include + +struct Base { virtual ~Base() = default; virtual int f() const = 0; }; +struct D1 : Base { int f() const override { return 1; } }; +struct D2 : Base { int f() const override { return 2; } }; + +int main() +{ + std::polymorphic a{std::in_place_type}; + std::polymorphic b{std::in_place_type}; + a.swap(b); + assert(a->f() == 2 && b->f() == 1); +} +``` +* std::polymorphic[color ff0000] +* std::in_place_type[link /reference/utility/in_place_type_t.md] + +### 出力 +``` +``` + + +## バージョン +### 言語 +- C++26 + +### 処理系 +- [Clang](/implementation.md#clang): 22 [mark noimpl] +- [GCC](/implementation.md#gcc): 16.1 [mark verified] +- [Visual C++](/implementation.md#visual_cpp): 2026 Update 2 [mark noimpl] + + +## 関連項目 +- [`std::polymorphic`](../polymorphic.md) + + +## 参照 +- [P3019R14 `indirect` and `polymorphic`: Vocabulary Types for Composite Class Design](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3019r14.pdf) diff --git a/reference/memory/polymorphic/swap_free.md b/reference/memory/polymorphic/swap_free.md new file mode 100644 index 0000000000..f680893d8a --- /dev/null +++ b/reference/memory/polymorphic/swap_free.md @@ -0,0 +1,68 @@ +# swap +* memory[meta header] +* std[meta namespace] +* polymorphic[meta class] +* function[meta id-type] +* cpp26[meta cpp] + +```cpp +friend constexpr void swap(polymorphic& lhs, polymorphic& rhs) noexcept(see below); +``` + +## 概要 +2つの`polymorphic`オブジェクトを交換する。*Hidden friends*として定義される。 + + +## 効果 +`lhs.swap(rhs)`と等価。 + + +## 例外 +以下と等価な`noexcept`指定を持つ: + +```cpp +noexcept(noexcept(lhs.swap(rhs))) +``` + + +## 例 +```cpp example +#include +#include + +struct Base { virtual ~Base() = default; virtual int f() const = 0; }; +struct D1 : Base { int f() const override { return 1; } }; +struct D2 : Base { int f() const override { return 2; } }; + +int main() +{ + std::polymorphic a{std::in_place_type}; + std::polymorphic b{std::in_place_type}; + swap(a, b); // ADLにより非メンバswapが呼ばれる + assert(a->f() == 2 && b->f() == 1); +} +``` +* std::polymorphic[color ff0000] +* std::in_place_type[link /reference/utility/in_place_type_t.md] + +### 出力 +``` +``` + + +## バージョン +### 言語 +- C++26 + +### 処理系 +- [Clang](/implementation.md#clang): 22 [mark noimpl] +- [GCC](/implementation.md#gcc): 16.1 [mark verified] +- [Visual C++](/implementation.md#visual_cpp): 2026 Update 2 [mark noimpl] + + +## 関連項目 +- [`std::polymorphic`](../polymorphic.md) + + +## 参照 +- [P3019R14 `indirect` and `polymorphic`: Vocabulary Types for Composite Class Design](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3019r14.pdf) diff --git a/reference/memory/polymorphic/valueless_after_move.md b/reference/memory/polymorphic/valueless_after_move.md new file mode 100644 index 0000000000..687f983f77 --- /dev/null +++ b/reference/memory/polymorphic/valueless_after_move.md @@ -0,0 +1,72 @@ +# valueless_after_move +* memory[meta header] +* std[meta namespace] +* polymorphic[meta class] +* function[meta id-type] +* cpp26[meta cpp] + +```cpp +constexpr bool valueless_after_move() const noexcept; +``` + +## 概要 +`*this`が無効値状態かどうかを判定する。`polymorphic`はムーブされたあとにのみ無効値状態となりうる。 + + +## 戻り値 +`*this`が無効値状態であれば`true`、そうでなければ`false`。 + + +## 例外 +投げない。 + + +## 例 +```cpp example +#include +#include + +struct Base { + virtual ~Base() = default; + virtual int f() const { return 0; } +}; +struct Derived : Base { + int x = 42; + Derived() = default; + Derived(int x) : x(x) {} + int f() const override { return x; } +}; + +int main() +{ + std::polymorphic a{std::in_place_type}; + assert(!a.valueless_after_move()); + + std::polymorphic b = std::move(a); + assert(a.valueless_after_move()); // ムーブ後は無効値状態 +} +``` +* std::polymorphic[color ff0000] +* std::in_place_type[link /reference/utility/in_place_type_t.md] + +### 出力 +``` +``` + + +## バージョン +### 言語 +- C++26 + +### 処理系 +- [Clang](/implementation.md#clang): 22 [mark noimpl] +- [GCC](/implementation.md#gcc): 16.1 [mark verified] +- [Visual C++](/implementation.md#visual_cpp): 2026 Update 2 [mark noimpl] + + +## 関連項目 +- [`std::polymorphic`](../polymorphic.md) + + +## 参照 +- [P3019R14 `indirect` and `polymorphic`: Vocabulary Types for Composite Class Design](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3019r14.pdf)