Skip to content

Commit 3bcf3e6

Browse files
committed
C++26対応としてspanのコンストラクタにinitializer_listをとるオーバーロードを追加 (close #1234)
1 parent c422171 commit 3bcf3e6

File tree

1 file changed

+63
-2
lines changed

1 file changed

+63
-2
lines changed

reference/span/span/op_constructor.md

Lines changed: 63 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ constexpr span(const span& other) noexcept = default; // (8) C++20
3535
template <class OtherElementType, size_t OtherExtent>
3636
constexpr explicit(extent != dynamic_extent && OtherExtent == dynamic_extent)
3737
span(const span<OtherElementType, OtherExtent>& s) noexcept; // (9) C++20
38+
39+
constexpr explicit(extent != dynamic_extent)
40+
span(std::initializer_list<value_type> il); // (10) C++26
3841
```
3942
* size_t[link /reference/cstddef/size_t.md]
4043
* array[link /reference/array/array.md]
@@ -57,6 +60,7 @@ constexpr explicit(extent != dynamic_extent && OtherExtent == dynamic_extent)
5760
- 動的な要素数をもつ`span`同士の変換
5861
- `span<T>`から`span<const T>`への変換
5962
- バイト数が同じ暗黙の型変換が可能な要素型をもつ`span`同士の変換
63+
- (10) : 初期化子リストから`span`オブジェクトを構築する
6064
6165
6266
## テンプレートパラメータ制約
@@ -88,6 +92,9 @@ constexpr explicit(extent != dynamic_extent && OtherExtent == dynamic_extent)
8892
- (9) :
8993
- `extent ==` [`dynamic_extent`](/reference/span/dynamic_extent.md) `|| OtherExtent ==` [`dynamic_extent`](/reference/span/dynamic_extent.md) `|| extent == OtherExtent`が`true`であること (受け取り側が[`dynamic_extent`](/reference/span/dynamic_extent.md)を持っていれば任意の`Extent`から変換できる)
9094
- `OtherElementType(*)[]`型が`ElementType(*)[]`型に変換可能であること
95+
- (10) :
96+
- [`is_const_v`](/reference/type_traits/is_const.md)`<element_type>`が`true`であること
97+
- (`std::span<const T>`に対してのみ使用できる)
9198
9299
93100
## 事前条件
@@ -106,6 +113,8 @@ constexpr explicit(extent != dynamic_extent && OtherExtent == dynamic_extent)
106113
- [`std::is_const_v`](/reference/type_traits/is_const.md)`<element_type>` が `false`であるとき、型 `R` はコンセプト [`std::ranges::borrowed_range`](/reference/ranges/borrowed_range.md) のモデルであること
107114
- (9) :
108115
- `extent`が[`dynamic_extent`](/reference/span/dynamic_extent.md)と等値でない場合、`extent`は[`s.size()`](size.md)と等値になる
116+
- (10) :
117+
- `extent`が[`dynamic_extent`](/reference/span/dynamic_extent.md)と等値でない場合、`extent`は[`il.size()`](/reference/initializer_list/initializer_list/size.md)と等値になる
109118
110119
111120
## 効果
@@ -114,6 +123,7 @@ constexpr explicit(extent != dynamic_extent && OtherExtent == dynamic_extent)
114123
- (4), (5), (6) : 範囲`[`[`data`](/reference/iterator/data.md)`(arr),` [`data`](/reference/iterator/data.md)`(arr) + N)`を参照する`span`オブジェクトを構築する
115124
- (7) : 範囲`[std::ranges::data(r), std::ranges::data(r) + std::ranges::size(r))`を参照する`span`オブジェクトを構築する
116125
- (9) : 範囲`[s.`[`data()`](data.md)`, s.`[`data()`](data.md) `+ s.`[`size()`](size.md)`)`を参照する`span`オブジェクトを構築する
126+
- (10) : 範囲`[il.`[`begin()`](/reference/initializer_list/initializer_list/begin.md)`, il.`[`begin()`](/reference/initializer_list/initializer_list/begin.md) `+ il.`[`size()`](/reference/initializer_list/initializer_list/size.md)`)`を参照する`span`オブジェクトを構築する
117127
118128
119129
## 事後条件
@@ -130,10 +140,20 @@ constexpr explicit(extent != dynamic_extent && OtherExtent == dynamic_extent)
130140
131141
132142
## 計算量
133-
- (1)-(9) : 定数時間
143+
- (1)-(10) : 定数時間
144+
145+
146+
## この機能が必要になった背景・経緯
147+
- (10) :
148+
- [`std::string_view`](/reference/string_view/basic_string_view.md)が文字列リテラル (たとえば`"abc"`) をとれるのと同様に、`std::span`クラスも[`std::initializer_list`](/reference/initializer_list/initializer_list.md)をとれるようにした
149+
150+
151+
## 備考
152+
- (10) : `std::span<const int> v = {1, 2, 3};` のような使い方は初期化子リストの寿命が尽きてしまうので注意。関数のパラメータを`span`として受け取るような使い方が想定される
134153
135154
136155
## 例
156+
### 基本的な使い方 (C++20)
137157
```cpp example
138158
#include <cassert>
139159
#include <span>
@@ -261,8 +281,47 @@ int main()
261281
* str.size()[link /reference/string/basic_string/size.md]
262282
* str.data()[link /reference/string/basic_string/data.md]
263283

264-
### 出力
284+
#### 出力
285+
```
286+
```
287+
288+
289+
### 初期化子リストからspanを構築する (C++26)
290+
```cpp example
291+
#include <iostream>
292+
#include <span>
293+
#include <vector>
294+
295+
void print_list(std::span<const int> s) {
296+
bool first = true;
297+
for (const int& x : s) {
298+
if (first) {
299+
first = false;
300+
}
301+
else {
302+
std::cout << ',';
303+
}
304+
std::cout << x;
305+
}
306+
std::cout << std::endl;
307+
}
308+
309+
int main()
310+
{
311+
std::vector<int> v = {1, 2, 3, 4, 5};
312+
print_list(v);
313+
314+
print_list({{3, 1, 4}}); // C++20からOK
315+
print_list({3, 1, 4}); // C++26からOK
316+
}
317+
```
318+
319+
320+
#### 出力
265321
```
322+
1,2,3,4,5
323+
3,1,4
324+
3,1,4
266325
```
267326
268327
## バージョン
@@ -283,3 +342,5 @@ int main()
283342
- [P1394R4 Range constructor for `std::span`](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1394r4.pdf)
284343
- [P1976R2 Fixed-size `span` construction from dynamic range](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p1976r2.html)
285344
- [P2117R0 C++ Standard Library Issues Resolved Directly In Prague](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p2117r0.html)
345+
- [P2447R6 `std::span` over an initializer list](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2447r6.html)
346+
- C++26から初期化子リストをとるコンストラクタが追加された

0 commit comments

Comments
 (0)