Skip to content

Commit

Permalink
memory: P1132R8 out_ptr_t,out_ptr追加(#1050)
Browse files Browse the repository at this point in the history
  • Loading branch information
yohhoy committed Jan 21, 2023
1 parent 6d599ab commit 382c5a5
Show file tree
Hide file tree
Showing 8 changed files with 373 additions and 1 deletion.
2 changes: 1 addition & 1 deletion lang/cpp23.md
Expand Up @@ -193,7 +193,7 @@ C++23とは、2023年中に改訂される予定の、C++バージョンの通


### メモリ
- [`<memory>`](/reference/memory.md)に、出力ポインタと入出力ポインタの抽象である[`std::out_ptr`](/reference/memory/out_ptr.md.nolink)[`std::inout_ptr`](/reference/memory/inout_ptr.md.nolink)を追加
- [`<memory>`](/reference/memory.md)に、レガシーC関数からスマートポインタへの直接出力をサポートする、スマートポインタアダプタ[`std::out_ptr`](/reference/memory/out_ptr.md)[`std::inout_ptr`](/reference/memory/inout_ptr.md.nolink)を追加
- [`std::unique_ptr`](/reference/memory/unique_ptr.md)クラスを`constexpr`に対応
- [`<memory>`](/reference/memory.md)に、オブジェクトの生存期間を開始することを明示する関数として、[`std::start_lifetime_as()`](/reference/memory/start_lifetime_as.md.nolink)[`std::start_lifetime_as_array()`](/reference/memory/start_lifetime_as_array.md.nolink)を追加
- [`<bit>`](/reference/bit.md)に、値のバイト入れ替え (エンディアン変換) を行う[`std::byteswap()`](/reference/bit/byteswap.md)関数を追加
Expand Down
11 changes: 11 additions & 0 deletions reference/memory.md
Expand Up @@ -90,6 +90,16 @@
| `auto_ptr` | 古い専有方式スマートポインタ(class template) | C++11から非推奨<br/> C++17で削除 |


## スマートポインタアダプタ

| 名前 | 説明 | 対応バージョン |
|------|------|-------|
| [`out_ptr_t`](memory/out_ptr_t.md) | スマートポインタへの出力サポート(class template) | C++23 |
| [`out_ptr`](memory/out_ptr.md) | スマートポインタへの出力サポートヘルパ関数(function template) | C++23 |
| [`inout_ptr_t`](memory/inout_ptr_t.md.nolink) | スマートポインタへの入出力サポート(class template) | C++23 |
| [`inout_ptr`](memory/inout_ptr.md.nolink) | スマートポインタへの入出力サポートヘルパ関数(function template) | C++23 |


## スマートポインタのアトミック操作

| 名前 | 説明 | 対応バージョン |
Expand Down Expand Up @@ -138,3 +148,4 @@
- [P0718R2 Revising `atomic_shared_ptr` for C++20](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0718r2.html)
- [P2051R0 C++ Standard Library Issues to be moved in Prague](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p2051r0.html)
- [P2186R2 Removing Garbage Collection Support](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2186r2.html)
- [P1132R8 out_ptr - a scalable output pointer abstraction](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p1132r8.html)
80 changes: 80 additions & 0 deletions reference/memory/out_ptr.md
@@ -0,0 +1,80 @@
# out_ptr
* memory[meta header]
* function template[meta id-type]
* std[meta namespace]
* cpp23[meta cpp]

```cpp
namespace std {
template<class Pointer = void, class Smart, class... Args>
auto out_ptr(Smart& s, Args&&... args);
}
```
## 概要
2重ポインタ`T**`引数経由で新規確保リソースへのポインタを返すレガシーC関数に対して、出力されたポインタ値をスマートポインタ`s`に格納するアダプタ[`out_ptr_t`](out_ptr_t.md)を返すヘルパ関数。
C++標準スマートポインタ[`std::shared_ptr`](shared_ptr.md)や[`std::unique_ptr`](unique_ptr.md)を始め、互換インタフェースをもつ任意のスマートポインタ型`Smart`を取り扱える。
説明用の`P`型を次のように定義する :
- [`is_void_v`](/reference/type_traits/is_void.md)`<Pointer>`が`false`ならば`Pointer`
- そうでなければ、`Smart::pointer`が有効な型名であれば`Smart::pointer`
- そうでなければ、`Smart::element_type*`が有効な型名であれば`Smart::element_type*`
- そうでなければ、[`pointer_traits`](pointer_traits.md)`<Smart>::element_type*`
## 戻り値
[`out_ptr_t`](out_ptr_t.md)`<Smart, P, Args&&...>(s,` [`std::forward<Args>`](/reference/utility/forward.md)`(args)...)`
## 例
### P1132R8引用
```cpp example
// Legacy C APIs
error_num c_api_create_handle(int seed_value, int** p_handle);
void c_api_delete_handle(int* handle);
// C++ program
#include <memory>
struct resource_deleter {
void operator()(int* handle) {
c_api_delete_handle(handle);
}
};
int main() {
std::unique_ptr<int, resource_deleter> resource(nullptr);
error_num err = c_api_create_handle(
24, std::out_ptr(resource)
);
if (err == C_API_ERROR_CONDITION) {
// handle errors
}
// resource.get() the out-value from the C API function
}
```
* std::out_ptr[color ff0000]


## バージョン
### 言語
- C++23

### 処理系
- [Clang](/implementation.md#clang): ??
- [GCC](/implementation.md#gcc): ??
- [ICC](/implementation.md#icc): ??
- [Visual C++](/implementation.md#visual_cpp): ??


## 関連項目
- [`out_ptr_t`](out_ptr_t.md)
- [`shared_ptr`](shared_ptr.md)
- [`unique_ptr`](unique_ptr.md)


## 参照
- [P1132R8 out_ptr - a scalable output pointer abstraction](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p1132r8.html)
58 changes: 58 additions & 0 deletions reference/memory/out_ptr_t.md
@@ -0,0 +1,58 @@
# out_ptr_t
* memory[meta header]
* class template[meta id-type]
* std[meta namespace]
* cpp23[meta cpp]

```cpp
namespace std {
template<class Smart, class Pointer, class... Args>
class out_ptr_t;
}
```
## 概要
2重ポインタ`T**`(=`Pointer*`)引数経由で新規確保リソースへのポインタを返すレガシーC関数に対して、取得されたポインタ値をスマートポインタに格納するアダプタクラス。
アダプタオブジェクトの生成には、[`std::out_ptr()`](out_ptr.md)ヘルパ関数を利用する。
C++標準スマートポインタ[`std::shared_ptr`](shared_ptr.md)や[`std::unique_ptr`](unique_ptr.md)を始め、互換インタフェースをもつ任意のスマートポインタ型`Smart`を取り扱える。
## テンプレートパラメータ制約
`Pointer`はCpp17NullablePointer要件を満たすこと
## 適格要件
`Smart`が[`shared_ptr`](shared_ptr.md)の特殊化かつ`sizeof...(Args) == 0`の場合、プログラムは不適格となる。
(根拠説明は[デストラクタ](out_ptr_t/op_destructor.md)を参照のこと。)
## メンバ関数
| 名前 | 説明 | 対応バージョン |
|-----------------|----------------|----------------|
| [`(constructor)`](out_ptr_t/op_constructor.md) | コンストラクタ | C++23 |
| [`(destructor)`](out_ptr_t/op_destructor.md) | デストラクタ | C++23 |
| [`operator Pointer*()`](out_ptr_t/op_pointer.md) | `Pointer*`への暗黙変換 | C++23 |
| [`operator void**()`](out_ptr_t/op_voidpp.md) | `void**`への暗黙変換 | C++23 |
## バージョン
### 言語
- C++23
### 処理系
- [Clang](/implementation.md#clang): ??
- [GCC](/implementation.md#gcc): ??
- [ICC](/implementation.md#icc): ??
- [Visual C++](/implementation.md#visual_cpp): ??
## 関連項目
- [`out_ptr()`](out_ptr.md)
- [`shared_ptr`](shared_ptr.md)
- [`unique_ptr`](unique_ptr.md)
## 参照
- [P1132R8 out_ptr - a scalable output pointer abstraction](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p1132r8.html)
45 changes: 45 additions & 0 deletions reference/memory/out_ptr_t/op_constructor.md
@@ -0,0 +1,45 @@
# コンストラクタ
* memory[meta header]
* std[meta namespace]
* out_ptr_t[meta class]
* function[meta id-type]
* cpp23[meta cpp]

```cpp
explicit out_ptr_t(Smart& smart, Args... args); // (1)
out_ptr_t(const out_ptr_t&) = delete; // (2)
```
## 概要
- (1) : `out_ptr_t`オブジェクトの構築。
- (2) : コピーコンストラクタ。コピー不可。
## 効果
(1) : `out_ptr_t`クラスの説明用メンバ変数`s`, `a`, `p`を下記の通り初期化する。
- `Smart&`型メンバ変数 : `s = smart;`
- `tuple<Args...>`型メンバ変数 : `a =` [`std::forward`](/reference/utility/forward.md)`<Args>(args)...;`
- `Pointer`型メンバ : `p = {};`
## バージョン
### 言語
- C++23
### 処理系
- [Clang](/implementation.md#clang): ??
- [GCC](/implementation.md#gcc): ??
- [ICC](/implementation.md#icc): ??
- [Visual C++](/implementation.md#visual_cpp): ??
## 関連項目
- [`out_ptr()`](../out_ptr.md)
- [`(destructor)`](op_destructor.md)
- [`operator Pointer*`](op_pointer.md)
- [`operator void**`](op_voidpp.md)
## 参照
- [P1132R8 out_ptr - a scalable output pointer abstraction](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p1132r8.html)
75 changes: 75 additions & 0 deletions reference/memory/out_ptr_t/op_destructor.md
@@ -0,0 +1,75 @@
# デストラクタ
* memory[meta header]
* std[meta namespace]
* out_ptr_t[meta class]
* function[meta id-type]
* cpp23[meta cpp]

```cpp
~out_ptr_t();
```

## 概要
指定した`Smart`型スマートポインタに、レガシーC関数呼び出しにより取得されたポインタ値を格納する。

スマートポインタへのポインタ値格納には、`Smart::reset()`メンバ関数、もしくは`Smart`オブジェクト構築+ムーブ代入`operator=`が利用される。

- オブジェクト単位でカスタムデリータを管理する[`std::shared_ptr<T>`](../shared_ptr.md)の場合、[`out_ptr_t`コンストラクタ](op_constructor.md)にてデリータオブジェクトを渡しておくことで、[`reset()`](../shared_ptr/reset.md)呼び出しの追加引数リストとして渡される。
この動作は[`out_ptr_t`](../out_ptr_t.md)クラステンプレートの適格要件にて強制される。
- 型レベルでカスタムデリータを管理する[`std::unique_ptr<T,D>`](../unique_ptr.md)の場合、[`reset()`](../unique_ptr/reset.md)呼び出しには取得ポインタ値のみが渡される。
- これ以外のスマートポインタ型では、同スマートポインタの動作セマンティクスに従う。


## 効果
説明用の`SP`型を下記の通り定義する :

- `Smart::pointer`が有効な型名であれば`Smart::pointer`
- そうでなければ、`Smart::element_type*`が有効な型名であれば`Smart::element_type*`
- そうでなければ、[`pointer_traits`](../pointer_traits.md)`<Smart>::element_type*`
- そうでなければ、`Pointer`

[説明用メンバ変数](op_constructor.md)`s`, `a`, `p`を用いて、以下と同じ効果を持つ :

-`s.reset(static_cast<SP>(p),` [`std::forward`](/reference/utility/forward.md)`<Args>(args)...)` が適格ならば、

```cpp
if (p) {
apply([&](auto&&... args) {
s.reset(static_cast<SP>(p), std::forward<Args>(args)...); }, std::move(a));
}
```
* apply[link /reference/tuple/apply.md]

- [`is_constructible_v`](/reference/type_traits/is_constructible.md)`<Smart, SP, Args...>``true`ならば、

```cpp
if (p) {
apply([&](auto&&... args) {
s = Smart(static_cast<SP>(p), std::forward<Args>(args)...); }, std::move(a));
}
```
* apply[link /reference/tuple/apply.md]

- そうでなければ、プログラムは不適格となる。


## バージョン
### 言語
- C++23

### 処理系
- [Clang](/implementation.md#clang): ??
- [GCC](/implementation.md#gcc): ??
- [ICC](/implementation.md#icc): ??
- [Visual C++](/implementation.md#visual_cpp): ??


## 関連項目
- [`out_ptr()`](../out_ptr.md)
- [`(constructor)`](op_constructor.md)
- [`operator Pointer*`](op_pointer.md)
- [`operator void**`](op_voidpp.md)


## 参照
- [P1132R8 out_ptr - a scalable output pointer abstraction](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p1132r8.html)
44 changes: 44 additions & 0 deletions reference/memory/out_ptr_t/op_pointer.md
@@ -0,0 +1,44 @@
# operator Pointer*
* memory[meta header]
* std[meta namespace]
* out_ptr_t[meta class]
* function[meta id-type]
* cpp23[meta cpp]

```cpp
operator Pointer*() const noexcept;
```

## 概要
`Pointer`型の[説明用メンバ変数](op_constructor.md)へのポインタを取得する。


## 事前条件
`*this`[`operator void**()`](op_voidpp.md)が呼び出されていないこと


## 戻り値
[`addressof`](../addressof.md)`(const_cast<Pointer&>(p))`


## 例外
投げない


## バージョン
### 言語
- C++23

### 処理系
- [Clang](/implementation.md#clang): ??
- [GCC](/implementation.md#gcc): ??
- [ICC](/implementation.md#icc): ??
- [Visual C++](/implementation.md#visual_cpp): ??


## 関連項目
- [`out_ptr()`](../out_ptr.md)


## 参照
- [P1132R8 out_ptr - a scalable output pointer abstraction](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p1132r8.html)
59 changes: 59 additions & 0 deletions reference/memory/out_ptr_t/op_voidpp.md
@@ -0,0 +1,59 @@
# operator void**
* memory[meta header]
* std[meta namespace]
* out_ptr_t[meta class]
* function[meta id-type]
* cpp23[meta cpp]

```cpp
operator void**() const noexcept;
```

## 概要
`Pointer`型の[説明用メンバ変数](op_constructor.md)へのポインタ値を、`void**`型にキャストして取得する。


## テンプレートパラメータ制約
[`is_same_v`](/reference/type_traits/is_same.md)`<Pointer, void*>``false`であること


## 適格要件
[`is_pointer_v`](/reference/type_traits/is_pointer.md)`<Pointer>``true`であること


## 事前条件
`*this`[`operator Pointer*()`](op_pointer.md)が呼び出されていないこと


## 戻り値
次のポインタ値`v`を返す :

- 初期値`*v``static_cast<void*>(p)`と等価であり、かつ
- `*this`の後続変更に続かない`*v`の変更は、`static_cast<void*>(p) == *v`のように、`*this`[デストラクト中](op_destructor.md)`p`の値に影響を与える。


## 例外
投げない


## 備考
`*this`の生存期間外での`*v`へのアクセスは未定義動作


## バージョン
### 言語
- C++23

### 処理系
- [Clang](/implementation.md#clang): ??
- [GCC](/implementation.md#gcc): ??
- [ICC](/implementation.md#icc): ??
- [Visual C++](/implementation.md#visual_cpp): ??


## 関連項目
- [`out_ptr()`](../out_ptr.md)


## 参照
- [P1132R8 out_ptr - a scalable output pointer abstraction](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p1132r8.html)

0 comments on commit 382c5a5

Please sign in to comment.