Skip to content

Commit d7c766e

Browse files
committed
C++26: 「構造化束縛でパックを導入できるようにする」を追加 (close #1376)
1 parent cd9dbc2 commit d7c766e

5 files changed

Lines changed: 107 additions & 3 deletions

File tree

GLOBAL_QUALIFY_LIST.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,7 @@
295295
* std::is_same_v[link /reference/type_traits/is_same.md]
296296
* std::is_same[link /reference/type_traits/is_same.md]
297297
* std::true_type[link /reference/type_traits/true_type.md]
298+
* std::decay_t[link /reference/type_traits/decay.md]
298299
* <typeindex>[link /reference/typeindex.md]
299300
* <typeinfo>[link /reference/typeinfo.md]
300301
* <unordered_map>[link /reference/unordered_map.md]
@@ -303,6 +304,7 @@
303304
* std::unordered_set[link /reference/unordered_set/unordered_set.md]
304305
* <utility>[link /reference/utility.md]
305306
* declval[link /reference/utility/declval.md]
307+
* std::forward_like[link /reference/utility/forward_like.md]
306308
* std::forward[link /reference/utility/forward.md]
307309
* std::make_pair[link /reference/utility/make_pair.md]
308310
* std::pair[link /reference/utility/pair.md]

implementation-status.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,7 @@
316316
| P2686R5: [`constexpr`構造化束縛の許可と、定数式への参照を定数式とする](/lang/cpp26/constexpr_structured_bindings_and_references_to_constexpr_variables.md.nolink) | 定数式に対する構造化束縛を許可し、関連する定数式への参照が定数式になるようにする | 15 | | | |
317317
| P3068R6: [定数評価での例外送出を許可](/lang/cpp26/allowing_exception_throwing_in_constant-evaluation.md) | 定数式の文脈での例外の送出と捕捉を許可 | | | | |
318318
| P2865R6: [非推奨だった配列の比較を削除](/lang/cpp26/remove_deprecated_array_comparisons.md.nolink) | C++20で非推奨となっていた配列比較を削除 | 15 | 20 | | |
319-
| P1061R10: [構造化束縛でパックを導入できるようにする](/lang/cpp26/structured_bindings_can_introduce_a_pack.md.nolink) | タプルを分解する際に複数の変数をパックとして宣言できるようにする。`auto [a, ...xs] = f();` | | | | |
319+
| P1061R10: [構造化束縛でパックを導入できるようにする](/lang/cpp26/structured_bindings_can_introduce_a_pack.md) | タプルを分解する際に複数の変数をパックとして宣言できるようにする。`auto [a, ...xs] = f();` | | | | |
320320
| P3176R0: [先行するカンマのない省略記号を非推奨化](/lang/cpp26/the_oxford_variadic_comma.md.nolink) | `void f(int, ...);`はOK。`void f(int...);`は非推奨 | 15 | 20 | | |
321321
| P3074R7: [共用体をトリビアルに未初期化できるようにする](/lang/cpp26/trivial_unions.md.nolink) | `constexpr`での`union U { T storage[N]; };`を許可し、未初期化にできるようにする | | | | |
322322
| P2900R14: [契約プログラミングをサポートする](/lang/cpp26/contracts.md.nolink) | 関数の事前条件、事後条件、不変条件を記述できるようにする | | | | |

lang/cpp17/structured_bindings.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -341,7 +341,8 @@ auto { w, {x, y}, z } = f(); // このような、tuple内にあるpairを同時
341341
- [C++20 構造化束縛した変数の参照キャプチャを許可](/lang/cpp20/reference_capture_of_structured_bindings.md)
342342
- [C++26 構造化束縛への属性を許可](/lang/cpp26/attributes_for_structured_bindings.md)
343343
- [C++26 条件式での構造化束縛の使用を許可](/lang/cpp26/structured_binding_declaration_as_a_condition.md)
344-
- [C++26 宣言のみで使用しない変数の名前として_をサポート](/lang/cpp26/nice_placeholder_with_no_name.md)
344+
- [C++26 宣言のみで使用しない変数の名前として`_`をサポート](/lang/cpp26/nice_placeholder_with_no_name.md)
345+
- [C++26 構造化束縛でパックを導入できるようにする](/lang/cpp26/structured_bindings_can_introduce_a_pack.md)
345346
346347
347348
## 参照

lang/cpp26.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ C++26とは、2026年中に改訂される予定の、C++バージョンの通
1818
| [返却された左辺値から暗黙変換された一時オブジェクトが参照に束縛されることを禁止する](/lang/cpp26/disallow_binding_a_returned_glvalue_to_a_temporary.md.nolink) | 寿命切れの変数によって引き起こされるバグを防止する |
1919
| [要素数不明の配列を集成体初期化する規則を明確化](/lang/cpp26/clarifying_rules_for_brace_elision_in_aggregate_initialization.md.nolink) | 配列要素の集成体初期化で`{}`が省略された場合の矛盾していた規定を修正 |
2020
| [未初期化変数の読み取りをエラー性動作とする](/lang/cpp26/erroneous_behavior_for_uninitialized_reads.md) | 初期化されていない自動変数の読み取りの安全性を規定する |
21-
| [構造化束縛でパックを導入できるようにする](/lang/cpp26/structured_bindings_can_introduce_a_pack.md.nolink) | タプルを分解する際に複数の変数をパックとして宣言できるようにする。`auto [a, ...xs] = f();` |
21+
| [構造化束縛でパックを導入できるようにする](/lang/cpp26/structured_bindings_can_introduce_a_pack.md) | タプルを分解する際に複数の変数をパックとして宣言できるようにする。`auto [a, ...xs] = f();` |
2222

2323

2424
### 文字列
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
# 構造化束縛でパックを導入できるようにする [P1061R10]
2+
* cpp26[meta cpp]
3+
4+
<!-- start lang caution -->
5+
6+
このページはC++26に採用される見込みの言語機能の変更を解説しています。
7+
8+
のちのC++規格でさらに変更される場合があるため[関連項目](#relative-page)を参照してください。
9+
10+
<!-- last lang caution -->
11+
12+
## 概要
13+
C++26では、構造化束縛でタプルを分解する際に、パックで受け取れるようになる。
14+
15+
```cpp
16+
std::tuple<X, Y, Z> f();
17+
18+
auto [x, y, z] = f(); // C++23: OK, C++26: OK
19+
auto [...xs] = f(); // C++26: OK. パックxsは長さ3でX, Y, Zが含まれる
20+
auto [x, ...rest] = f(); // C++26: OK. xはX、パックrestは長さ2でYとZが含まれる
21+
auto [x, y, z, ...rest] = f(); // C++26: OK. restは空のパック
22+
auto [x, ...rest, z] = f(); // C++26: OK. xはX、パックrestは長さ1でYに対応、zはZ
23+
auto [...a, ...b] = f(); // NG: 複数のパックは指定できない
24+
```
25+
26+
### std::apply()の実装改善
27+
タプルを展開して指定した関数の引数として転送して実行する[`std::apply()`](/reference/tuple/apply.md)関数のC++23での実装:
28+
29+
```cpp
30+
namespace detail {
31+
template <class F, class Tuple, std::size_t... I>
32+
constexpr decltype(auto) apply_impl(F &&f, Tuple &&t, std::index_sequence<I...>)
33+
{
34+
return std::invoke(std::forward<F>(f),
35+
std::get<I>(std::forward<Tuple>(t))...);
36+
}
37+
}
38+
39+
template <class F, class Tuple>
40+
constexpr decltype(auto) apply(F &&f, Tuple &&t)
41+
{
42+
return detail::apply_impl(
43+
std::forward<F>(f), std::forward<Tuple>(t),
44+
std::make_index_sequence<std::tuple_size_v<
45+
std::decay_t<Tuple>>>{});
46+
}
47+
```
48+
* std::invoke[link /reference/functional/invoke.md]
49+
* std::get[link /reference/tuple/tuple/get.md]
50+
* std::make_index_sequence[link /reference/utility/make_index_sequence.md]
51+
* std::tuple_size_v[link /reference/tuple/tuple_size.md]
52+
53+
C++26での実装:
54+
55+
```cpp
56+
template <class F, class Tuple>
57+
constexpr decltype(auto) apply(F &&f, Tuple &&t)
58+
{
59+
auto&& [...elems] = t;
60+
return std::invoke(std::forward<F>(f),
61+
std::forward_like<Tuple, decltype(elems)>(elems)...);
62+
}
63+
```
64+
* std::invoke[link /reference/functional/invoke.md]
65+
66+
67+
### 複数のタプルに対して畳み込み式を実行する
68+
C++23の場合:
69+
70+
```cpp
71+
template <class P, class Q>
72+
auto dot_product(P p, Q q) {
73+
return std::apply([&](auto... p_elems){
74+
return std::apply([&](auto... q_elems){
75+
return (... + (p_elems * q_elems));
76+
}, q)
77+
}, p);
78+
}
79+
```
80+
* std::apply[link /reference/tuple/apply.md]
81+
82+
C++26の場合:
83+
84+
```
85+
template <class P, class Q>
86+
auto dot_product(P p, Q q) {
87+
// applyが必要なくなる
88+
auto&& [...p_elems] = p;
89+
auto&& [...q_elems] = q;
90+
return (... + (p_elems * q_elems));
91+
}
92+
```
93+
94+
95+
## <a id="relative-page" href="#relative-page">関連項目</a>
96+
- [C++11 可変引数テンプレート](/lang/cpp11/variadic_templates.md)
97+
- [C++17 構造化束縛](/lang/cpp17/structured_bindings.md)
98+
99+
100+
## 参照
101+
- [P1061R10 Structured Bindings can introduce a Pack](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p1061r10.html)

0 commit comments

Comments
 (0)