最終更新日時: 2025年08月31日 21時46分41秒 (JST)
Raclamusi が更新

履歴 編集

<mdspan>

# std::mdspan::推論補助(C++23)

    namespace std {
      template<class CArray>
        requires (is_array_v<CArray> && rank_v<CArray> == 1)
        mdspan(CArray&)
          -> mdspan<remove_all_extents_t<CArray>, extents<size_t, extent_v<CArray, 0>>>;  // (1)

      template<class Pointer>
        requires (is_pointer_v<remove_reference_t<Pointer>>)
        mdspan(Pointer&&)
          -> mdspan<remove_pointer_t<remove_reference_t<Pointer>>, extents<size_t>>;  // (2)

      template<class ElementType, class... Integrals>
        requires ((is_convertible_v<Integrals, size_t> && ...) && sizeof...(Integrals) > 0)
        explicit mdspan(ElementType*, Integrals...)
          -> mdspan<ElementType, dextents<size_t, sizeof...(Integrals)>>;           // (3) C++23
      template<class ElementType, class... Integrals>
        requires ((is_convertible_v<Integrals, size_t> && ...) && sizeof...(Integrals) > 0)
        explicit mdspan(ElementType*, Integrals...)
          -> mdspan<ElementType, extents<size_t, maybe-static-ext<Integrals>...>>;  // (3) C++26

      template<class ElementType, class OtherIndexType, size_t N>
        mdspan(ElementType*, span<OtherIndexType, N>)
          -> mdspan<ElementType, dextents<size_t, N>>;  // (4)

      template<class ElementType, class OtherIndexType, size_t N>
        mdspan(ElementType*, const array<OtherIndexType, N>&)
          -> mdspan<ElementType, dextents<size_t, N>>;  // (5)

      template<class ElementType, class IndexType, size_t... ExtentsPack>
        mdspan(ElementType*, const extents<IndexType, ExtentsPack...>&)
          -> mdspan<ElementType, extents<IndexType, ExtentsPack...>>;  // (6)

      template<class ElementType, class MappingType>
        mdspan(ElementType*, const MappingType&)
          -> mdspan<ElementType,
                    typename MappingType::extents_type,
                    typename MappingType::layout_type>;  // (7)

      template<class MappingType, class AccessorType>
        mdspan(const typename AccessorType::data_handle_type&,
               const MappingType&,
               const AccessorType&)
          -> mdspan<typename AccessorType::element_type,
                    typename MappingType::extents_type,
                    typename MappingType::layout_type,
                    AccessorType>;                      // (8)
    }

## 概要

`std::mdspan`クラステンプレートの型推論補助。

## 備考

推論補助(2)により、コンパイル時に要素数を取得できないポインタ型引数からは0次元`mdspan`が推論される。

## 例

    #include <cassert>
    #include <array>
    #include <span>
    #include <mdspan>
    #include <type_traits>

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

    int main()
    {
      int arr[] = {1, 2, 3, 4, 5, 6};

      { // (1) : 1次元配列型から型推論
        std::mdspan m1{arr};
        static_assert(m1.rank() == 1 && m1.rank_dynamic() == 0);
        static_assert(m1.static_extent(0) == 6);
        // m1 := 静的要素数 6 の1次元配列ビュー

        // 2次元配列型からは型推論できない
        //   int arr2d[2][3] = {{1, 2, 3}, {4, 5, 6}};
        //   std::mdspan m1_ng{arr2d};
        // 下記は推論補助(2)により0次元mdspanとなる
        //   std::mdspan m1_d0{&arr2d[0][0]};
      }
      { // (2) : ポインタ型から型推論
        int* ptr = arr;
        std::mdspan m2{ptr};
        static_assert(m2.rank() == 0);
        assert(m2[] == *ptr);
        // m2 := 0次元配列ビュー
      }
      { // (3) : C++23 要素数リストから型推論
        std::mdspan m3a{arr, 2, 3};
        static_assert(m3a.rank_dynamic() == 2);
        assert(m3a.size() == 6);
        // m3a := 動的要素数 2x3 の2次元配列ビュー
      }
      { // (3) : C++26 整数定数要素数リストから型推論
        std::mdspan m3b{arr, Int<2>, Int<3>};
        static_assert(m3b.rank_dynamic() == 0);
        assert(m3b.size() == 6);
        // m3b := 静的要素数 2x3 の2次元配列ビュー
      }
      { // (4) : 要素数spanから型推論
        int exts[] = {2, 3};
        std::mdspan m4{arr, std::span{exts}};
        static_assert(m4.rank_dynamic() == 2);
        assert(m4.size() == 6);
        // m4 := 動的要素数 2x3 の2次元配列ビュー
      }
      { // (5) : 要素数arrayから型推論
        std::array exts{2, 3};
        std::mdspan m5{arr, exts};
        static_assert(m5.rank_dynamic() == 2);
        assert(m5.size() == 6);
        // m5 := 動的要素数 2x3 の2次元配列ビュー
      }
      { // (6) : 多次元配列サイズから型推論
        std::extents<size_t, 2, std::dynamic_extent> ext{3};
        std::mdspan m6{arr, ext};
        static_assert(m6.rank() == 2 && m6.rank_dynamic() == 1);
        assert(m6.size() == 6);
        // m6 := 静的要素数2 x 動的要素数3 の2次元配列ビュー
      }
      { // (7) : レイアウトマッピングから型推論
        using Ext2D = std::dextents<size_t, 2>;
        std::layout_stride::mapping<Ext2D> map{Ext2D{2, 2}, std::array{3, 1}};
        std::mdspan m7{arr, map};
        static_assert(m7.rank_dynamic() == 2);
        assert(m7.size() == 4);
        // m7 := 動的要素数 2x2（ストライド幅=[3,1]） の2次元配列ビュー
      }
      { // (8) : レイアウトマッピング＋要素アクセサから型推論
        using Ext2D = std::dextents<size_t, 2>;
        std::layout_stride::mapping<Ext2D> map{Ext2D{2, 2}, std::array{3, 1}};
        std::default_accessor<const int> acc;
        std::mdspan m8{arr, map, acc};
        static_assert(m8.rank_dynamic() == 2);
        assert(m8.size() == 4);
        // m8 := 動的要素数 2x2（ストライド幅=[3,1]） の読み取り専用2次元配列ビュー
      }
    }

### 出力

## バージョン

### 言語

- C++23

### 処理系

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

## 関連項目

- `extents`
- LayoutMapping
- AccessorPolicy

## 参照

- P0009R18 MDSPAN
- P3029R1 Better `mdspan`'s CTAD
  - C++26から、(3)で静的要素数への推論がサポートされる。