最終更新日時: 2026年03月21日 23時12分53秒 (JST)
Raclamusi が更新

履歴 編集

function
<forward_list>

# std::forward_list::コンストラクタ(C++11)

    forward_list();           // (1) C++14
    constexpr forward_list(); // (1) C++26

    explicit forward_list(const Allocator& a);           // (2) C++14
    constexpr explicit forward_list(const Allocator& a); // (2) C++26

    explicit forward_list(const Allocator& a = Allocator()); // (1) + (2) C++11まで

    forward_list(size_type n,
                 const T& value,
                 const Allocator& a = Allocator());   // (3) C++11
    constexpr
      forward_list(size_type n,
                   const T& value,
                   const Allocator& a = Allocator()); // (3) C++26

    explicit
      forward_list(size_type n);                      // (4) C++11
    explicit
      forward_list(size_type n,
                   const Allocator& a = Allocator()); // (4) C++14
    constexpr explicit
      forward_list(size_type n,
                   const Allocator& a = Allocator()); // (4) C++26

    template <class InputIterator>
    forward_list(InputIterator first,
                 InputIterator last,
                 const Allocator& a = Allocator());   // (5) C++11
    template <class InputIterator>
    constexpr
      forward_list(InputIterator first,
                   InputIterator last,
                   const Allocator& a = Allocator()); // (5) C++26

    forward_list(const forward_list& x);           // (6) C++11
    constexpr forward_list(const forward_list& x); // (6) C++26

    forward_list(forward_list&& x);           // (7) C++11
    constexpr forward_list(forward_list&& x); // (7) C++26

    forward_list(const forward_list& x,
                 const Allocator& a);                    // (8) C++11
    forward_list(const forward_list& x,
                 const type_identity_t<Allocator>& a);   // (8) C++23
    constexpr
      forward_list(const forward_list& x,
                   const type_identity_t<Allocator>& a); // (8) C++26

    forward_list(forward_list&& x,
                 const Allocator& a);                     // (9) C++11
    forward_list(forward_list&& x,
                 const type_identity_t<Allocator>& a);    // (9) C++23
    constexpr
      forward_list(forward_list&& x,
                   const type_identity_t<Allocator>& a);  // (9) C++26

    forward_list(initializer_list<T> il,
                 const Allocator& a = Allocator());   // (10) C++11
    constexpr
      forward_list(initializer_list<T> il,
                   const Allocator& a = Allocator()); // (10) C++26

    template <container-compatible-range<T> R>
    forward_list(from_range_t,
                 R&& rg,
                 const Allocator& a = Allocator());   // (11) C++23
    template <container-compatible-range<T> R>
    constexpr
      forward_list(from_range_t,
                   R&& rg,
                   const Allocator& a = Allocator()); // (11) C++26

## 概要

`forward_list`オブジェクトを、以下に示す通りの要素で初期化する。

## 効果

- (1) : デフォルトコンストラクタ。空のコンテナを作る。
- (2) : アロケータを指定して空のコンテナを作る。
- (1) + (2) : デフォルトコンストラクタ。アロケータを指定して空のコンテナを作る。
- (3) : `value` のコピーを `n` 個要素として保持した `forward_list` オブジェクトを構築する。
- (4)
  - C++11 : `n` 個の `T()` で初期化された要素を保持した `forward_list` オブジェクトを構築する。
  - C++14 : アロケータを指定して `n` 個の `T()` で初期化された要素を保持した `forward_list` オブジェクトを構築する。
- (5) : イテレータ範囲`[first, last)` を要素としてコピーした `forward_list` オブジェクトを構築する。
- (6) : コピーコンストラクタ。`x` と同じ要素を保持した `forward_list` オブジェクトを構築する。
- (7) : ムーブコンストラクタ。`x` の指す先を自分の領域として `forward_list` オブジェクトを構築する。
- (8) : アロケータを指定したコピーコンストラクタ
- (9) : アロケータを指定したムーブコンストラクタ
- (10) : 初期化子リストを受け取るコンストラクタ。`forward_list(il.begin(), il.end(), a)` と等価。
- (11) : Range `rg` の要素をコピーした `forward_list` オブジェクトを構築する。

## 計算量

- (1), (2) : 定数時間
- (3) : `n` に対して線形時間
- (4) : `n` に対して線形時間
- (5) : `distance(first, last)`に対して線形時間
- (6) : `x` の要素数に対して線形時間
- (7) : 定数時間
- (8) : `x` の要素数に対して線形時間
- (9) : `x.get_allocator() == a` であれば、定数時間。そうでなければ `x` の要素数に対して線形時間
- (10) : `il` の要素数に対して線形時間
- (11) : `rg` の要素数に対して線形時間

## 備考

- イテレータ範囲コンストラクタ `template <class InputIterator> forward_list(InputIterator first, InputIterator last, const Allocator& a = Allocator())` は、`InputIterator` が入力イテレータの要件を満たさなければオーバーロード解決に参加しない。

- C++14 では、`explicit forward_list(const Allocator& a = Allocator())` がデフォルト引数を使用しない 2 つのオーバーロードに分割された。
  これは、デフォルトコンストラクタに `explicit` が付いていると、

      std::forward_list<int> fl = {};

  のようなコード（C++11 から導入された、コピーリスト初期化によるデフォルトコンストラクタ呼び出し）がエラーになってしまうためである。

- C++14 では、`explicit forward_list(size_type n)` に引数が追加され、`explicit forward_list(size_type n, const Allocator& a = Allocator())` に変更された。
  これは、変更されないと `n` のみを引数にとるアロケータ使用構築（uses-allocator construction）に失敗してしまうためである。 具体的には、C++11 では以下のようなコードがエラーになってしまう。

      #include <list>
      #include <forward_list>
      #include <scoped_allocator>

      int main()
      {
        using fli = std::forward_list<int>;
        std::list<fli, std::scoped_allocator_adaptor<std::allocator<fli>>> l;
        l.emplace_back(10u);
      }

- C++23 では、(8) と (9) のアロケータパラメータの型が `const Allocator&` から `const type_identity_t<Allocator>&` に変更された。 これは、クラステンプレートのテンプレート引数推論 (CTAD) の際に、コピー/ムーブ元の `forward_list` から推論される `Allocator` と、アロケータ引数から推論される型が異なる場合に推論が失敗する問題を修正するためである。`type_identity_t` で包むことで、アロケータ引数が非推論コンテキストとなり、アロケータの型はコピー/ムーブ元のみから推論されるようになる。

## 例

    #include <iostream>
    #include <forward_list>
    #include <utility>

    template <class T>
    void print(const char* name, const std::forward_list<T>& ls)
    {
      std::cout << name << " : ";
      for (const T& x : ls) {
        std::cout << x << ' ';
      }
      std::cout << std::endl;
    }

    int main()
    {
      // (1) デフォルト構築
      std::forward_list<int> ls1;
      ::print("ls1", ls1);

      // (4) n個の要素を持つリストを作成
      std::forward_list<int> ls2(3);
      ::print("ls2", ls2);

      // (3) n個の指定された値を要素を持つリストを作成
      std::forward_list<int> ls3(3, 1);
      ::print("ls3", ls3);

      // (5) 範囲から構築
      std::forward_list<int> ls4(ls3.begin(), ls3.end());
      ::print("ls4", ls4);

      // (6) コピー構築
      std::forward_list<int> ls5 = ls4;
      ::print("ls5", ls5);

      // (7) ムーブ構築
      std::forward_list<int> ls6 = std::move(ls5);
      ::print("ls6", ls6);

      // (10) 初期化子リストで構築
      std::forward_list<int> ls7 = {1, 2, 3};
      ::print("ls7", ls7);
    }

### 出力

    ls1 :
    ls2 : 0 0 0
    ls3 : 1 1 1
    ls4 : 1 1 1
    ls5 : 1 1 1
    ls6 : 1 1 1
    ls7 : 1 2 3

## バージョン

### 言語

- C++11

### 処理系

- Clang: ??
- GCC: 4.7.0 ✅
- ICC: ??
- Visual C++: 2010 ✅, 2012 ✅, 2013 ✅, 2015 ✅, 2017 ✅
  - (1)と(2)は2010当初からC++14のとおり実装されている。
  - (5)のオーバーロードも、2010当初から、デフォルト実引数を用いずアロケータを引数に取るものと取らないもの、2つのオーバーロードで実現されている。
  - (8), (9)のオーバーロードは2012から。
  - (3) `initializer_list`のオーバーロードは2013から。

## 参照

- N2679 Initializer Lists for Standard Containers(Revision 1)
  - (10)の経緯となる提案文書
- LWG 2193. Default constructors for standard library containers are explicit
  `explicit forward_list(const Allocator& a = Allocator())` を 2 つのオーバーロードに分割するきっかけとなったレポート
- LWG 2210. Missing allocator-extended constructor for allocator-aware containers
  `explicit forward_list(size_type n)` にアロケータ引数を追加するきっかけとなったレポート
  なお、Discussion の例はアロケータの型が誤っているので注意
- P1518R2 Stop Overconstraining Allocators in Container Deduction Guides
  - C++23でのアロケータ引数を`type_identity_t`で包む変更
- P3372R3 constexpr containers and adaptors