最終更新日時: 2026年07月22日 16時08分23秒 (JST)
rotarymars が更新

履歴 編集

function template
<mdspan>

# std::submdspan_extents(C++26)

    namespace std {
      template<class IndexType, class... Extents, class... SliceSpecifiers>
      constexpr auto submdspan_extents(const extents<IndexType, Extents...>& src,
                                       SliceSpecifiers... raw_slices);
    }

## 概要

多次元配列サイズ`extents`と各次元からの要素取り出し（スライス）方式を指定して、新しい多次元配列サイズ`extents`を取得する。

各次元からの要素取り出し方式は、`submdspan`を参照のこと。

説明用のパック`slices`を以下の通り宣言する。

    auto [...slices] = submdspan_canonicalize_slices(src, raw_slices...);

## テンプレートパラメータ制約

`sizeof...(SliceSpecifiers)`が`sizeof...(Extents)`と等しいこと。

## 適格要件

`src`の各次元インデクス`k`に対して、

- `SliceSpecifiers...[k]`が`IndexType`の`submdspan`スライス型であり、かつ
- `decltype(slices...[k])`が`extents<IndexType, Extents...>`のk番目次元の有効`submdspan`スライス型(valid `submdspan` slice type)であること。

## 事前条件

`src`の各次元インデクス`k`に対して、`slices...[k]`が`src`のk番目次元の有効`submdspan`スライス(valid `submdspan` slice)であること。

## 戻り値

説明用の型`SubExtents`を、下記を満たす`extents`の特殊化とする。

- `SubExtents::rank()`が`MAP_RANK(slices, Extents::rank())`に等しく、かつ
- `slices...[k]`の型が縮約スライス型(collapsing slice type)ではない`Extents`の各次元インデクス`k`に対して、説明用の`S_k`を`slices...[k]`の型としたとき、`SubExtents::static_extent(MAP_RANK(slices, k))`が下記と等しいこと。
  - 型`S_k`が`full_extent_t`のとき、`SubExtents::static_extent(k)`、そうでなければ、
  - 型`S_k`が`strided_slice`の特殊化かつメンバ型`S_k::extent_type`が`constant_wrapper<IndexType(0)>`のとき、値`0`、そうでなければ
  - 型`S_k`が`strided_slice`の特殊化かつメンバ型`extent_type`および`stride_type`がいずれも`constant_wrapper`の特殊化であるとき、`1 + ((S_k::extent_type::value - 1) / S_k::stride_type::value)`
  - そうでなければ、`dynamic_extent`

以下を満たす`SubExtents`型の値`ext`を返す。

- `slices...[k]`の型が縮約スライス型(collapsing slice type)ではない`extents<IndexType, Extents...>`の各次元インデクス`k`について、説明用の`s_k`を`slices...[k]`としたとき、`ext.extent(MAP_RANK(slices, k))`が下記に等しいこと。
  - `s_k`の型が`strided_slice`の特殊化であるとき、`s_k.extent == 0 ? 0 : 1 + (s_k.extent - 1) / s_k.stride`
  - そうでなければ、`src`のk番目の要素に対して`submdspan`スライス範囲である半開区間`[L, U)`に対して、`U - L`

## 例

    #include <cassert>
    #include <concepts>
    #include <mdspan>
    #include <type_traits>
    #include <utility>

    template <int N>
    constexpr auto Int = std::integral_constant<int, N>{};

    int main()
    {
      std::extents<size_t, 10> exts{};

      auto ext0 = std::submdspan_extents(exts, 0);
      static_assert(std::same_as<decltype(ext0), std::extents<size_t>>);

      auto ext1 = std::submdspan_extents(exts, std::full_extent);
      static_assert(std::same_as<decltype(ext1), std::extents<size_t, 10>>);

      auto ext2 = std::submdspan_extents(exts, std::pair{Int<2>, Int<8>});
      static_assert(std::same_as<decltype(ext2), std::extents<size_t, 6>>);

      auto ext3 = std::submdspan_extents(exts, std::strided_slice{0, Int<0>, 1});
      static_assert(std::same_as<decltype(ext3), std::dextents<size_t, 1>>);
      assert(ext3.extent(0) == 0);

      auto ext4 = std::submdspan_extents(exts, std::strided_slice{0, Int<10>, Int<3>});
      static_assert(std::same_as<decltype(ext4), std::extents<size_t, 4>>);

      auto ext5 = std::submdspan_extents(exts, std::pair{2, 8});
      static_assert(std::same_as<decltype(ext5), std::dextents<size_t, 1>>);
      assert(ext5.extent(0) == 6);
    }

### 出力

## バージョン

### 言語

- C++26

### 処理系

- Clang: ??
- GCC: ??
- ICC: ??
- Visual C++: ??

## 関連項目

- `submdspan`
- `full_extent`
- `strided_slice`

## 参照

- P2630R4 Submdspan
- P3663R3 Future-proof `submdspan_mapping`