最終更新日時(UTC):
が更新

履歴 編集

function
<span>

std::span::コンストラクタ(C++20)

constexpr span() noexcept;                                             // (1)

template <class It>
constexpr span(It first, size_type count);                             // (2)

template <class It, class End>
constexpr span(It first, End last);                                    // (3)

template <size_t N>
constexpr span(element_type (&arr)[N]) noexcept;                       // (4)

template <size_t N>
constexpr span(array<value_type, N>& arr) noexcept;                    // (5)

template <size_t N>
constexpr span(const array<value_type, N>& arr) noexcept;              // (6)

template <class R>
constexpr span(R&& r);                                                 // (7)

constexpr span(const span& other) noexcept = default;                  // (8)

template <class OtherElementType, size_t OtherExtent>
constexpr span(const span<OtherElementType, OtherExtent>& s) noexcept; // (9)

概要

spanオブジェクトを構築する。

  • (1) : デフォルトコンストラクタ。空のspanオブジェクトを構築する
  • (2) : 参照範囲として先頭要素を指すイテレータと、そこからの要素数を指定して、それらの要素を参照するspanオブジェクトを構築する
  • (3) : 参照範囲として先頭要素を指すイテレータと、末尾要素の次を指すイテレータを指定して、それらの要素を参照するspanオブジェクトを構築する
  • (4) : 指定された組み込み配列の全体を参照するspanオブジェクトを構築する
  • (5) : 指定された非const左辺値参照のstd::arrayの全体を参照するspanオブジェクトを構築する
  • (6) : 指定されたconst左辺値参照のstd::arrayの全体を参照するspanオブジェクトを構築する
  • (7) : 指定された、メモリ連続性をもつイテレータを持つオブジェクトの要素全体を参照するspanオブジェクトを構築する
  • (8) : コピーコンストラクタ。otherと同じ範囲を参照するspanオブジェクトを構築する
  • (9) : テンプレートパラメータの異なるspanオブジェクトを変換する。以下のような変換ができる:
    • 静的な要素数をもつspanから動的な要素数をもつspanへの変換。
    • 動的な要素数をもつspan同士の変換
    • span<T>からspan<const T>への変換
    • バイト数が同じ暗黙の型変換が可能な要素型をもつspan同士の変換

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

  • (1) :
    • Extent == dynamic_extent || Extent == 0trueであること
      • -1はオーバーフローによって正の最大値になるのでfalse
  • (2) :
    • Ustd::remove_reference_t<std::iter_reference_t<It>>とするとき
      • It はコンセプト std::contiguous_iterator を満たしていること
      • std::is_convertible_v<U(*)[], element_type(*)[]>true であること。(その意図は、イテレータ参照型から element_type への qualification conversionsのみを許可することである。)
  • (3) :
    • Ustd::remove_reference_t<std::iter_reference_t<It>>とするとき
      • It はコンセプト std::contiguous_iterator を満たしていること
      • std::is_convertible_v<U(*)[], element_type(*)[]>true であること。(その意図は、イテレータ参照型から element_type への qualification conversionsのみを許可することである。)
      • End はコンセプト std::sized_sentinel_for<It> を満たしていること
      • std::is_convertible_v<End, size_t>falseであること
  • (4), (5), (6) :
  • (7) :
    • Ustd::remove_reference_t<std::iter_reference_t<R>>とするとき
      • extent == dynamic_extenttrueであること
      • R はコンセプト std::ranges::contiguous_range 及び std::ranges::sized_range を満たしていること
      • R がコンセプト std::ranges::safe_range を満たすか、std::is_const_v<element_type>trueであること
      • std::remove_cvref_t<R>std::spanの特殊化ではないこと
      • std::remove_cvref_t<R>std::arrayの特殊化ではないこと
      • std::is_array_v<std::remove_cvref_t<R>>false であること
      • std::is_convertible_v<U(*)[], element_type(*)[]>true であること。(その意図は、イテレータ参照型から element_type への qualification conversionsのみを許可することである。)
  • (9) :
    • Extent == dynamic_extent || Extent == OtherExtenttrueであること (受け取り側がdynamic_extentを持っていれば任意のExtentから変換できる)
    • OtherElementType(*)[]型がElementType(*)[]型に変換可能であること

事前条件

  • (2) :
    • [first, first + count)が妥当な範囲であること
    • It はコンセプト std::contiguous_iterator のモデルであること
    • メンバ定数extentdyanmic_extentと等値ではない場合、countextentが等値であること
  • (3) :
    • [first, last)が妥当な範囲であること
    • メンバ定数extentdyanmic_extentと等値ではない場合、last - firstextentが等値であること
    • It はコンセプト std::contiguous_iterator のモデルであること
    • End はコンセプト std::sized_sentinel_for<It> のモデルであること
  • (7) :
    • R はコンセプト std::ranges::contiguous_range 及び std::ranges::sized_range のモデルであること
    • std::is_const_v<element_type>falseであるとき、型 Rstd::ranges::safe_range のモデルであること

効果

  • (2) : 範囲[first, first + count)を参照するspanオブジェクトを構築する
  • (3) : 範囲[first, last)を参照するspanオブジェクトを構築する
  • (4), (5), (6) : 範囲[data(arr), data(arr) + N)を参照するspanオブジェクトを構築する
  • (7) : 範囲[std::ranges::data(r), std::ranges::data(r) + std::ranges::size(r))を参照するspanオブジェクトを構築する
  • (9) : 範囲[s.data(), s.data() + s.size())を参照するspanオブジェクトを構築する

事後条件

例外

  • (1), (2), (3), (4), (5), (6) : 投げない
  • (7) : コンテナ型によっては、std::ranges::data(r)std::ranges::size(r)の呼び出しがなんらかの例外を送出する可能性がある

計算量

  • (1)-(9) : 定数時間

#include <cassert>
#include <span>
#include <vector>
#include <array>
#include <string>

int main()
{
  std::vector<int> v = {1, 2, 3, 4, 5};

  // (1) デフォルトコンストラクタ
  {
    // 長さ0の参照範囲をもつspanオブジェクト
    std::span<int, 0> s1;
    assert(s1.empty());

    // 動的な要素数をもつspanオブジェクト
    std::span<int> s2;
    assert(s2.empty());

    // 以下はコンパイルエラーになる。
    // 長さ1以上のspanは、参照範囲を設定しなければならない
    // std::span<int, 1> s3{};
  }

  // (2) イテレータと要素数の組を指定
  {
    // vの先頭3要素を参照する。
    std::span<int> s{v.begin(), 3};
    assert(s.size() == 3);
    assert(s[0] == 1);
    assert(s[1] == 2);
    assert(s[2] == 3);
  }

  // (3) 範囲を指定
  {
    std::span<int> s{v.begin(), v.begin() + 3};
    assert(s.size() == 3);
    assert(s[0] == 1);
    assert(s[1] == 2);
    assert(s[2] == 3);
  }

  // (4) 組み込み配列への参照を指定
  {
    int ar[] = {1, 2, 3, 4, 5};
    std::span<int> s{ar};
    assert(s.size() == 5);
    assert(s.data() == ar); // 元の配列をコピーせず、参照している
  }

  // (5) std::arrayオブジェクトへの参照を指定
  {
    std::array ar = {1, 2, 3, 4, 5};
    std::span<int> s{ar};
    assert(s.size() == ar.size());
    assert(s.data() == ar.data());
  }

  // (6) const std::arrayオブジェクトへの参照を指定
  {
    std::array ar = {1, 2, 3, 4, 5};
    const auto& car = ar;
    std::span<const int> s{car};

    assert(s.size() == car.size());
    assert(s.data() == car.data());
  }

  // (7) メモリの連続性をもつイテレータをもつオブジェクトの要素全体を参照させる
  {
    std::span<int> s1{v};
    assert(s1.size() == v.size());
    assert(s1.data() == v.data());

    // std::string_viewの代わり
    std::string str = "Hello";
    std::span<char> s2{str};
    assert(s2.size() == str.size());
    assert(s2.data() == str.data());
  }

  // (8) コピーコンストラクタ
  {
    std::span<int> s1{v};
    std::span<int> s2 = s1;

    // コピー元とコピー先が同じ範囲を参照する
    assert(s1.data() == v.data());
    assert(s2.data() == v.data());
  }

  // (9) 変換コンストラクタ
  {
    int ar[] = {1, 2, 3};

    std::span<int, 3> s1{ar};
    std::span<int> s2 = s1;
    std::span<int> s3 = s2.first(2);
    std::span<const int> s4 = s3;

    assert(s4.size() == 2);
    assert(s4.data() == ar);
  }
}

出力

バージョン

言語

  • C++20

処理系

  • Clang: (10.0.0 現在、実装は P1394R4 以前の不完全なものである)
  • GCC: 10.0.1
  • Visual C++: ??

参照