Skip to content

Commit

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


### メモリ
- [`<memory>`](/reference/memory.md)に、レガシーC関数からスマートポインタへの直接出力をサポートする、スマートポインタアダプタ[`std::out_ptr`](/reference/memory/out_ptr.md)[`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)を追加
- [`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
4 changes: 2 additions & 2 deletions reference/memory.md
Expand Up @@ -96,8 +96,8 @@
|------|------|-------|
| [`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 |
| [`inout_ptr_t`](memory/inout_ptr_t.md) | スマートポインタへの入出力サポート(class template) | C++23 |
| [`inout_ptr`](memory/inout_ptr.md) | スマートポインタへの入出力サポートヘルパ関数(function template) | C++23 |


## スマートポインタのアトミック操作
Expand Down
83 changes: 83 additions & 0 deletions reference/memory/inout_ptr.md
@@ -0,0 +1,83 @@
# inout_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 inout_ptr(Smart& s, Args&&... args);
}
```
## 概要
2重ポインタ`T**`引数経由で既存リソースを解放してから新規確保リソースへのポインタを返すレガシーC関数に対して、出力されたポインタ値をスマートポインタ`s`に格納するアダプタ[`inout_ptr_t`](inout_ptr_t.md)を返すヘルパ関数。
リソース占有管理セマンティクスを提供するC++標準スマートポインタ[`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*`
## 戻り値
[`inout_ptr_t`](inout_ptr_t.md)`<Smart, P, Args&&...>(s,` [`std::forward<Args>`](/reference/utility/forward.md)`(args)...)`
## 備考
スマートポインタアダプタ`inout_ptr`は、リソース共有管理セマンティクスを提供する[`std::shared_ptr`](shared_ptr.md)をサポートしない。
これは、共有管理されている既存リソースの所有権を放棄させるインタフェース(`release`)を提供しないためである。
## 例
### P1132R8引用
```cpp example
// Legacy C APIs
error_num c_api_re_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_re_create_handle(
24, std::inout_ptr(resource)
);
if (err == C_API_ERROR_CONDITION) {
// handle errors
}
// resource.get() the out-value from the C API function
}
```
* std::inout_ptr[color ff0000]


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

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


## 関連項目
- [`inout_ptr_t`](inout_ptr_t.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)
56 changes: 56 additions & 0 deletions reference/memory/inout_ptr_t.md
@@ -0,0 +1,56 @@
# inout_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 inout_ptr_t;
}
```
## 概要
2重ポインタ`T**`(=`Pointer*`)引数経由で既存リソースを解放してから新規確保リソースへのポインタを返すレガシーC関数に対して、取得されたポインタ値をスマートポインタに格納するアダプタクラス。
アダプタオブジェクトの生成には、[`std::inout_ptr()`](inout_ptr.md)ヘルパ関数を利用する。
C++標準スマートポインタ[`std::unique_ptr`](unique_ptr.md)を始め、互換インタフェースをもつ任意のスマートポインタ型`Smart`を取り扱える。
## テンプレートパラメータ制約
`Pointer`はCpp17NullablePointer要件を満たすこと
## 適格要件
`Smart`が[`shared_ptr`](shared_ptr.md)の特殊化の場合、プログラムは不適格となる。
## メンバ関数
| 名前 | 説明 | 対応バージョン |
|-----------------|----------------|----------------|
| [`(constructor)`](inout_ptr_t/op_constructor.md) | コンストラクタ | C++23 |
| [`(destructor)`](inout_ptr_t/op_destructor.md) | デストラクタ | C++23 |
| [`operator Pointer*()`](inout_ptr_t/op_pointer.md) | `Pointer*`への暗黙変換 | C++23 |
| [`operator void**()`](inout_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): ??
## 関連項目
- [`inout_ptr()`](inout_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)
52 changes: 52 additions & 0 deletions reference/memory/inout_ptr_t/op_constructor.md
@@ -0,0 +1,52 @@
# コンストラクタ
* memory[meta header]
* std[meta namespace]
* inout_ptr_t[meta class]
* function[meta id-type]
* cpp23[meta cpp]

```cpp
explicit inout_ptr_t(Smart& smart, Args... args); // (1)
inout_ptr_t(const inout_ptr_t&) = delete; // (2)
```
## 概要
- (1) : `inout_ptr_t`オブジェクトの構築。
- (2) : コピーコンストラクタ。コピー不可。
## 効果
(1) : `inout_ptr_t`クラスの説明用メンバ変数`s`, `a`, `p`を下記の通り初期化する。
- `Smart&`型メンバ変数`s` : `smart`
- `tuple<Args...>`型メンバ変数`a` : [`std::forward`](/reference/utility/forward.md)`<Args>(args)...`
- `Pointer`型メンバ`p` :
- [`is_pointer_v`](/reference/type_traits/is_pointer.md)`<Smart>`が`true`ならば、`smart`
- そうでなければ、`smart.get()`
## 備考
実装によっては`s.release()`を呼び出すかもしれない。
コンストラクタで`release`メンバ関数を呼び出さない場合は、[デストラクタ](op_destructor.md)にて呼び出される。
## バージョン
### 言語
- C++23
### 処理系
- [Clang](/implementation.md#clang): ??
- [GCC](/implementation.md#gcc): ??
- [ICC](/implementation.md#icc): ??
- [Visual C++](/implementation.md#visual_cpp): ??
## 関連項目
- [`inout_ptr()`](../inout_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)
87 changes: 87 additions & 0 deletions reference/memory/inout_ptr_t/op_destructor.md
@@ -0,0 +1,87 @@
# デストラクタ
* memory[meta header]
* std[meta namespace]
* inout_ptr_t[meta class]
* function[meta id-type]
* cpp23[meta cpp]

```cpp
~inout_ptr_t();
```

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

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


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

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

説明用の文`release-statement`を下記の通り定義する :

- [コンストラクタ](op_constructor.md)`s.release()`を呼び出さない実装であれば、`s.release()`
- そうでなければ、空文

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

- [`is_pointer_v`](/reference/type_traits/is_pointer.md)`<Smart>``true`ならば、

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

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

```cpp
if (p) {
apply([&](auto&&... args) {
release-statement;
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) {
release-statement;
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): ??


## 関連項目
- [`inout_ptr_t()`](../inout_ptr_t.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/inout_ptr_t/op_pointer.md
@@ -0,0 +1,44 @@
# operator Pointer*
* memory[meta header]
* std[meta namespace]
* inout_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): ??


## 関連項目
- [`inout_ptr()`](../inout_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 a7b1a5e

Please sign in to comment.