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

履歴 編集

function
<span>

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

constexpr span() noexcept;                                             // (1)
constexpr span(pointer ptr, index_type count);                         // (2)
constexpr span(pointer first, pointer 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 Container>
constexpr span(Container& cont);                                       // (7)

template <class Container>
constexpr span(const Container& cont);                                 // (8)

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

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

概要

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

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

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

  • (1) :
    • Extent == dynamic_extent || Extent == 0trueであること
      • -1はオーバーフローによって正の最大値になるのでfalse
  • (4), (5), (6) :
  • (7), (8) :
    • extent == dynamic_extenttrueであること
    • Containerspan型ではないこと
    • Containerarray型ではないこと
    • is_array_v<Container>falseであること (Containerが組み込み配列型ではないこと)
    • data(cont)と式size(size)が妥当であること (メモリの連続性をもつコンテナであること)
    • remove_pointer_t<decltype(data(arr)))>(*)[]型がElementType(*)[]型に変換可能であること
  • (11) :
    • Extent == dynamic_extent || Extent == OtherExtenttrueであること (受け取り側がdynamic_extentを持っていれば任意のExtentから変換できる)
    • OtherElementType(*)[]型がElementType(*)[]型に変換可能であること

事前条件

  • (2) :
    • [ptr, ptr + count)が妥当な範囲であること
    • メンバ定数extentdyanmic_extentと等値ではない場合、countextentが等値であること
  • (3) :
    • [first, last)が妥当な範囲であること
    • メンバ定数extentdyanmic_extentと等値ではない場合、last - firstextentが等値であること
  • (7), (8) :
    • [data(cont), data(cont) + size(cont))が妥当な範囲であること

効果

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

事後条件

例外

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

計算量

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

備考

  • (2) : イテレータと要素数の組ではなく、ポインタと要素数の組であることに注意
    • 例として、std::vectorstd::arrayのイテレータが環境・状況によってはポインタとして定義されるかもしれないため、イテレータを指定しても動作する可能性はある。しかし、それでは他の環境では動作しない可能性が高いため、イテレータではなくポインタを指定すること
  • (2) : 第2引数の要素数は、(3)とのオーバーロードをあいまいにしないために、std::size_t型にキャストして渡したほうがよい

    • 例として、整数リテラル0はヌルポインタとみなされるため、(2)と(3)があいまいになる。
      std::vector<int> v = {1, 2, 3, 4, 5};
      //std::span<int, 3> s1{v.data(), 0};  // コンパイルエラー : (2)と(3)があいまい
      std::span<int, 3> s2{v.data(), static_cast<std::size_t>(0)}; // OK
      
  • (3) : イテレータ範囲ではなく、ポインタ範囲であることに注意。(2)と同様に、イテレータを指定してはならない

#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要素を参照する。
    // {v.begin(), 3}と書いてはならない
    std::span<int> s{v.data(), 3};
    assert(s.size() == 3);
    assert(s[0] == 1);
    assert(s[1] == 2);
    assert(s[2] == 3);
  }

  // (3) ポインタ範囲を指定
  {
    // vの先頭3要素を参照する。
    // {v.begin(), v.begin() + 3}と書いてはならない
    std::span<int> s{v.data(), v.data() + 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) メモリの連続性をもつconstコンテナを参照させる
  {
    const auto& cv = v;
    std::span<const int> s{cv};
    assert(s.size() == cv.size());
    assert(s.data() == cv.data());
  }

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

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

  // (10) ムーブコンストラクタ。コピーと同じ
  {
    std::span<int> s1{v};
    std::span<int> s2 = std::move(s1);

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

  // (11) 変換コンストラクタ
  {
    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

処理系

参照