Skip to content

Commit

Permalink
C++20 : P0777R1対応
Browse files Browse the repository at this point in the history
  • Loading branch information
yohhoy committed Jan 13, 2023
1 parent b40b1a8 commit df3cf15
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 15 deletions.
43 changes: 33 additions & 10 deletions reference/concepts/Invoke.md
Expand Up @@ -4,6 +4,11 @@
* named requirement[meta id-type]
* [meta namespace]

C++における関数呼び出しという性質を抽象化しまとめた、仮想操作 *INVOKE* を定義する。

C++17からは、本仮想操作を実体化した[`invoke`](/reference/functional/invoke.md)関数テンプレートが提供される。


## 用語定義
- *call-signature* とは、戻り値型に続けて丸括弧の中に0個以上の引数型を並べたものである。 *cf.* `int ( std::string, int )`
- *callable-type* とは、関数呼び出し演算子を適用できる型 ( 関数、関数への参照、関数へのポインタ、`operator ()` をオーバーロードした型もしくはそれを(直接または間接的に) `public` 継承した型 ) もしくはメンバへのポインタ型を指す。
Expand Down Expand Up @@ -41,17 +46,35 @@
- それ以外の場合は、*INVOKE*`(f, t1, t2, ..., tN)` の実行結果の戻り値が型 `R` に暗黙的に変換されること。
3. すべての *call-wrapper* は、*MoveConstructible* でなければならない。

## 要件(C++20)
1. 仮想操作 *INVOKE*`(f, t1, t2, ..., tN)` を次のように定義する。
- `f` が型 `T` のメンバ関数へのポインタであり、[`is_baseof_v`](/reference/type_traits/is_base_of.md)`<T, `[`remove_cvref_t`](/reference/type_traits/remove_cvref.md)`<decltype(t1)>> == true`(`t1` が `T` または `T` を継承した型のオブジェクト/参照)であるとき、 `(t1.*f)(t2, ..., tN)` と同じ効果を持つ。
- `f` が型 `T` のメンバ関数へのポインタであり、[`remove_cvref_t`](/reference/type_traits/remove_cvref.md)`<decltype(t1)>`が[`reference_wrapper<T>`](/reference/functional/reference_wrapper.md)(`t1`が[`reference_wrapper`](/reference/functional/reference_wrapper.md)の特殊化)であるとき、 `(t1.get().*f)(t2, ..., tN)` と同じ効果を持つ。
- `f` が型 `T` のメンバ関数へのポインタであり、 `t1` が上記の条件に当てはまらない場合(例えば、t1が`T`のポインタ)、`((*t1).*f)(t2, ..., tN)` と同じ効果を持つ。
- `N == 1` で、`f` が型 `T` のメンバオブジェクトへのポインタであり、[`is_baseof_v`](/reference/type_traits/is_base_of.md)`<T, `[`remove_cvref_t`](/reference/type_traits/remove_cvref.md)`<decltype(t1)>> == true`(`t1` が `T` または `T` を継承した型のオブジェクト/参照)であるとき、 `t1.*f` と同じ効果を持つ。
- `N == 1` で、`f` が型 `T` のメンバオブジェクトへのポインタであり、[`remove_cvref_t`](/reference/type_traits/remove_cvref.md)`<decltype(t1)>`が[`reference_wrapper<T>`](/reference/functional/reference_wrapper.md)(`t1`が[`reference_wrapper`](/reference/functional/reference_wrapper.md)の特殊化)であるとき、 `t1.get().*f` と同じ効果を持つ。
- `N == 1` で、`f` が型 `T` のメンバオブジェクトへのポインタであり、`t1` が上記の条件に当てはまらない場合(例えば、t1が`T`のポインタ)、 `(*t1).*f` と同じ効果を持つ。
- 上記の条件のどれにも当てはまらない場合、 `f(t1, t2, ..., tN)` と同じ効果を持つ。
2. *INVOKE*`<R>(f, t1, t2, ..., tN)` を次のように定義する。
- `R`が`void`かそのcv修飾の場合は、`static_cast<void>(`*INVOKE*`(f, t1, t2, ..., tN))`。
- それ以外の場合は、*INVOKE*`(f, t1, t2, ..., tN)` の実行結果の戻り値が型 `R` に暗黙的に変換されること。
3. すべての *call-wrapper* は、*Cpp17MoveConstructible* かつ *Cpp17Destructible* でなければならない。


## まとめ
[第1引数がメンバ関数へのポインタの場合でも非静的メンバデータへのポインタの場合でも,第2引数がクラスオブジェクトへの参照の場合でもポインタの場合でもポインタっぽいものの場合でも,なんか知らんけどそれっぽく上手くいく](https://twitter.com/Cryolite/status/216814363221303296) ように取り計らった操作のことである。

## 関連項目
- [invoke](/reference/functional/invoke.md)
- [function](/reference/functional/function.md)
- [reference_wrapper](/reference/functional/reference_wrapper.md)
- [bind](/reference/functional/bind.md)
- [mem_fn](/reference/functional/mem_fn.md)
- [not_fn](/reference/functional/not_fn.md)
- [thread](/reference/thread/thread.md)
- [async](/reference/future/async.md)
- [packaged_task](/reference/future/packaged_task.md)
- [call_once](/reference/mutex/call_once.md)
- [`function`](/reference/functional/function.md)
- [`reference_wrapper`](/reference/functional/reference_wrapper.md)
- [`bind`](/reference/functional/bind.md)
- [`mem_fn`](/reference/functional/mem_fn.md)
- [`not_fn`](/reference/functional/not_fn.md)
- [`thread`](/reference/thread/thread.md)
- [`async`](/reference/future/async.md)
- [`packaged_task`](/reference/future/packaged_task.md)
- [`call_once`](/reference/mutex/call_once.md)

## 参照
- [P0777R1 Treating Unnecessary `decay`](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0777r1.pdf)
- C++20から`decay_t``remove_cvref_t`へ変更。
3 changes: 2 additions & 1 deletion reference/optional/optional/op_constructor.md
Expand Up @@ -221,6 +221,7 @@ int main()
- [LWG Issue 2842. `in_place_t` check for `optional::optional(U&&)` should decay `U`](https://wg21.cmeerw.net/lwg/issue2842)
- 説明の簡略化のため、このオーバーロードで`in_place_t`への言及は現在していない
- [LWG Issue 2900. The copy and move constructors of `optional` are not `constexpr`](https://wg21.cmeerw.net/lwg/issue2900)
- [P0777R1 Treating Unnecessary `decay`](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0777r1.pdf)
- [P0892R2 `explicit(bool)`](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0892r2.html)
- C++20での`explicit(bool)`構文への対応
- [P0602R4 `variant` and `optional` should propagate copy/move triviality](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0602r4.html)
- [P0602R4 `variant` and `optional` should propagate copy/move triviality](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0602r4.html)
13 changes: 12 additions & 1 deletion reference/tuple/apply.md
Expand Up @@ -38,8 +38,17 @@ constexpr decltype(auto) apply-impl(F&& f, Tuple&& t, std::index_sequence<I...>)
* std::invoke[link /reference/functional/invoke.md]
* std::forward[link /reference/utility/forward.md]

次と等価である。
C++17 : 次と等価である。
```cpp
return apply-impl(std::forward<F>(f), std::forward<Tuple>(t),
std::make_index_sequence<std::tuple_size_v<std::decay_t<Tuple>>>{});
```
* std::tuple_size_v[link tuple_size.md]
* std::make_index_sequence[link /reference/utility/make_index_sequence.md]
* std::forward[link /reference/utility/forward.md]
* std::decay_t[link /reference/type_traits/decay.md]

C++20 : 次と等価である。
```cpp
return apply-impl(std::forward<F>(f), std::forward<Tuple>(t),
std::make_index_sequence<std::tuple_size_v<std::remove_reference_t<Tuple>>>{});
Expand Down Expand Up @@ -110,5 +119,7 @@ hello
- [P0220R0 Adopt Library Fundamentals TS for C++17](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0220r0.html)
- [P0220R1 Adopt Library Fundamentals V1 TS Components for C++17 (R1)](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0220r1.html)
- [C++1z タプルを展開して関数呼び出しするapply関数 - Faith and Brave - C++で遊ぼう](https://faithandbrave.hateblo.jp/entry/2016/08/18/184315)
- [P0777R1 Treating Unnecessary `decay`](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0777r1.pdf)
- C++20から効果説明の`decay_t`を`remove_cvref_t`へ変更。
- [P2517R1 Add a conditional `noexcept` specification to `std::apply`](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2517r1.html)
- C++23から条件付きで`noexcept`例外指定が行われる。
9 changes: 6 additions & 3 deletions reference/variant/variant/op_constructor.md
Expand Up @@ -60,9 +60,10 @@ constexpr explicit variant(in_place_index_t<I>,
- (4) :
- C++17 : ここで説明用に、`*this`が保持している型`Tj`と、そのインデックス値`j`を定義する。`Types...`の各型`Ti`に対して擬似的な関数`FUN(Ti)`を定義したとして、`FUN(`[`std::forward`](/reference/utility/forward.md)`<T>(t))`呼び出しによって選択されたオーバーロードされた関数のパラメータ型を、構築してその後含まれる値の型を`Tj`とする
- C++20 : ここで説明用に、`*this`が保持している型`Tj`と、そのインデックス値`j`を定義する。`Types...`の各型`Ti`を、縮小変換を受け付けない型であり (`Ti x[] = {`[`std::forward`](/reference/utility/forward.md)`<T>(t)};`)、CV修飾付き`bool`の場合にCV修飾を外した`bool`型になるとして、その型に対して擬似的な関数`FUN(Ti)`を定義したとして、`FUN(`[`std::forward`](/reference/utility/forward.md)`<T>(t))`呼び出しによって選択されたオーバーロードされた関数のパラメータ型を、構築してその後含まれる値の型を`Tj`とする
- [`is_same_v`](/reference/type_traits/is_same.md)`<`[`decay_t`](/reference/type_traits/decay.md)`<T>, variant>`が`false`であること
- 型[`decay_t`](/reference/type_traits/decay.md)`<T>`が[`in_place_type_t`](/reference/utility/in_place_type_t.md)および[`in_place_index_t`](/reference/utility/in_place_index_t.md)の特殊化ではないこと
- [`is_constructible_v`](/reference/type_traits/is_constructible.md)`<Tj, T>`が`true`であること
- C++17 : [`is_same_v`](/reference/type_traits/is_same.md)`<`[`decay_t`](/reference/type_traits/decay.md)`<T>, variant>`が`false`であること
- C++20 : [`is_same_v`](/reference/type_traits/is_same.md)`<`[`remove_cvref_t`](/reference/type_traits/remove_cvref.md)`<T>, variant>`が`false`であること
- C++17 : 型[`decay_t`](/reference/type_traits/decay.md)`<T>`が[`in_place_type_t`](/reference/utility/in_place_type_t.md)および[`in_place_index_t`](/reference/utility/in_place_index_t.md)の特殊化ではないこと
- C++20 : 型[`remove_cvref_t`](/reference/type_traits/remove_cvref.md)`<T>`が[`in_place_type_t`](/reference/utility/in_place_type_t.md)および[`in_place_index_t`](/reference/utility/in_place_index_t.md)の特殊化ではないこと - [`is_constructible_v`](/reference/type_traits/is_constructible.md)`<Tj, T>`が`true`であること
- 式`FUN(`[`std::forward`](/reference/utility/forward.md)`<T>(x))`が適格であること
- (5) :
- `Types...`内に`T`が一度だけ現れること
Expand Down Expand Up @@ -364,3 +365,5 @@ int main()
- [LWG Issue 2901 Variants cannot properly support allocators](https://cplusplus.github.io/LWG/issue2901)
- [P0608R3 A sane variant converting constructor](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0608r3.html)
- [P0602R4 `variant` and `optional` should propagate copy/move triviality](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0602r4.html)
- [P0777R1 Treating Unnecessary `decay`](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0777r1.pdf)
- C++20からテンプレートパラメータ制約の`decay_t``remove_cvref_t`へ変更。

0 comments on commit df3cf15

Please sign in to comment.