最終更新日時(UTC): 2026年02月17日 14時22分33秒
Akira Takahashi が更新

履歴 編集

function
<set>

# std::set::コンストラクタ

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

    explicit set(const Compare& comp,
                 const Allocator& = Allocator()); // (2) C++14
    constexpr explicit
      set(const Compare& comp,
          const Allocator& = Allocator());        // (2) C++26

    explicit
      set(const Compare& comp = Compare(),
          const Allocator& alloc = Allocator()); // (1) + (2) C++03

    explicit set(const Allocator& alloc);           // (3) C++11
    constexpr explicit set(const Allocator& alloc); // (3) C++26

    template <class InputIterator>
    set(InputIterator first,
        InputIterator last,
        const Compare& comp = Compare(),
        const Allocator& alloc = Allocator());   // (4) C++03
    template <class InputIterator>
    constexpr
      set(InputIterator first,
          InputIterator last,
          const Compare& comp = Compare(),
          const Allocator& alloc = Allocator()); // (4) C++26

    template <class InputIterato>
    set(InputIterator first,
        InputIterator last,
        const Allocator& a);   // (5) C++14
    template <class InputIterato>
    constexpr
      set(InputIterator first,
          InputIterator last,
          const Allocator& a); // (5) C++26

    set(const set& x);           // (6) C++03
    constexpr set(const set& x); // (6) C++26

    set(set&& y);           // (7) C++11
    constexpr set(set&& y); // (7) C++26

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

    set(set&& y, const Allocator& alloc);                            // (9) C++11
    set(set&& y, const type_identity_t<Allocator>& alloc);           // (9) C++23
    constexpr set(set&& y, const type_identity_t<Allocator>& alloc); // (9) C++26

    set(initializer_list<value_type> init,
        const Compare& comp = Compare(),
        const Allocator& alloc = Allocator()); // (10) C++11
    constexpr
      set(initializer_list<value_type> init,
          const Compare& comp = Compare(),
          const Allocator& alloc = Allocator()); // (10) C++26

    set(initializer_list<value_type> init,
        const Allocator& a); // (11) C++14
    constexpr
      set(initializer_list<value_type> init,
          const Allocator& a); // (11) C++26

    template <container-compatible-range <value_type> R>
    set(from_range_t,
        R&& rg,
        const Compare& comp = Compare(),
        const Allocator& alloc = Allocator()); // (12) C++23
    template <container-compatible-range <value_type> R>
    constexpr
      set(from_range_t,
          R&& rg,
          const Compare& comp = Compare(),
          const Allocator& alloc = Allocator()); // (12) C++26

    template <container-compatible-range <value_type> R>
    set(from_range_t,
        R&& rg,
        const Allocator& alloc); // (13) C++23
    template <container-compatible-range <value_type> R>
    constexpr
      set(from_range_t,
          R&& rg,
          const Allocator& alloc); // (13) C++26

## 概要

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

## 効果

- (1) : デフォルトコンストラクタ。要素数が空の`set`オブジェクトを構築する。
- (2) : 比較関数オブジェクトを受け取るコンストラクタ。受け取った比較関数オブジェクトを、このコンテナでの要素比較に使用する。要素数が空の`set`オブジェクトを構築する。
- (1) + (2) : デフォルトコンストラクタ。空のコンテナを構築する。
- (3) : アロケータを別で受け取り、要素数が空の`set`オブジェクトを構築する。
- (4) : イテレータ範囲 `[first, last)` のコンテンツで構築する。
- (5) : (4)のコンストラクタを `set(first, last, Compare(), a)` のように呼び出して、`set`オブジェクトを構築する。
- (6), (8) : コピーコンストラクタ。`x`のコンテンツのコピーでコンテナを構築する。もし `alloc` が与えられなかった場合、アロケータを `std::allocator_traits<allocator_type>::select_on_container_copy_construction(x.get_allocator())` の呼び出しによって取得する。
- (7), (9) : ムーブコンストラクタ。`y` のコンテンツをムーブすることでコンテナを構築する。もし `alloc` が与えられなかった場合、アロケータを `y` に属しているアロケータをムーブして取得する。
- (10) : 初期化リスト `init` のコンテンツでコンテナを構築する。
- (11) : (10)のコンストラクタを `set(init, Compare(), a)` のように呼び出して、`set`オブジェクトを構築する。
- (12) : Range `rg` の要素で `set` オブジェクトを構築する。
- (13) : (12)のコンストラクタを `set(from_range, rg, Compare(), alloc)` のように呼び出して、`set`オブジェクトを構築する。

## 計算量

- (1), (2), (3) : 定数時間。
- (4), (5) : `comp` によって既にソート済みである場合は、イテレータ間の距離（コピーコンストラクト）。未ソートのシーケンスの場合は、それらの距離について N * logN （ソート、コピーコンストラクト）。
- (6), (8) : `x` の `size` に対して線形時間（全要素をコピー構築する）。
- (7), (9) : 定数時間。ただし、`alloc` が与えられてかつ `alloc != y.get_allocator()` の場合は線形時間。
- (10), (11) : `comp` によって既にソート済みである場合は、`init` のサイズ（コピーコンストラクト）。未ソートの `init` の場合は、`init` のサイズについて N * logN （ソート、コピーコンストラクト）。
- (12), (13) : `comp` によって既にソート済みである場合は、`rg` のサイズ（コピーコンストラクト）。未ソートの `rg` の場合は、`rg` のサイズについて N * logN （ソート、コピーコンストラクト）。

## 備考

- C++14 では、デフォルトコンストラクタを (1) + (2) の形式から (1) の形式に分離して残りを (2) の形式（`comp` のデフォルト引数を削除）にした。 これは、デフォルトコンストラクタに `explicit` が付いていると、

      std::set<int> s = {};

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

- C++14 では、(5) に形式が新たに追加された。 これは、イテレータ範囲 `[first, last)` のみを引数にとるアロケータ使用構築（uses-allocator construction）に失敗してしまうためである。 具体的には、C++11 では以下のようなコードがエラーになってしまう。

      #include <list>
      #include <set>
      #include <scoped_allocator>
      #include <iterator>
      #include <memory>

      int main()
      {
        using sii = std::set<int>;
        std::list<sii, std::scoped_allocator_adaptor<std::allocator<sii>>> ls;
        int a[] = {1, 2, 3};
        ls.emplace_back(std::begin(a), std::end(a));
      }

  なお、C++14 では同様の理由で (11) の形式も新たに追加されているが、こちらは存在しなくてもエラーとはならない。
  （`set(init, alloc)` の形式の構築では、(11) の形式が無い場合でも (10) の形式を用いて `init` から一時 `set` が構築され、`alloc` と共に (9) の形式に引き渡される）

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

## 例

    #include <iostream>
    #include <set>

    int main()
    {
      int values[] = { 5, 2, 4, 1, 0, 0, 9 };
      std::set<int> c1(values, values + 7);
      std::set<int> c2(c1);

      std::cout << "Size of c1: " << c1.size() << std::endl;
      std::cout << "Size of c2: " << c2.size() << std::endl;
    }

### 出力

    Size of c1: 6
    Size of c2: 6

## 関連項目

名前 | 説明
--- | ---
`operator=` | 代入演算子
`insert` | 要素を挿入する

## 参照

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