最終更新日時: 2025年07月09日 00時33分39秒 (JST)
Akira Takahashi が更新

履歴 編集

class template
<memory>

# std::uses_allocator(C++11)

    namespace std {
      template <class T, class Alloc>
      struct uses_allocator;

      template <class T, class Alloc>
      inline constexpr bool uses_allocator_v = uses_allocator<T, Alloc>::value; // C++17 から
    }

## 概要

型 `T` が `Alloc` 型のアロケータオブジェクトを用いた uses-allocator 構築をする際に、実際にアロケータオブジェクトを使用するかを調べる。

このクラスが `true_type` から派生する場合、以下のいずれかの構築が可能である：

- `T(allocator_arg, alloc, args...)` のように、第1引数に `allocator_arg`、第2引数に `Alloc` 型のアロケータオブジェクト `alloc` をとる構築。
- `T(args..., alloc)` のように、最後の引数として `Alloc` 型のアロケータオブジェクト `alloc` をとる構築。

このクラスのデフォルト実装は、型 `T` が `public` なメンバ型 `allocator_type` を持っており、その型が `Alloc` から変換可能であれば `true_type` から派生し、そうでなければ `false_type` から派生する。

型 `T` が `Alloc` から変換可能なメンバ型 `allocator_type` を持っていないが上記いずれかの構築が可能な場合は、`true_type` から派生した本クラステンプレートの特殊化を提供することで、アロケータを用いた構築をサポートしていることを示すことが可能である。

### uses-allocator 構築

「uses-allocator 構築」とは、型 `T` のオブジェクト `obj` を構築する際に、引数とアロケータを `T` のコンストラクタに適切に引き渡すような構築方法である。

アロケータのオブジェクトを `alloc`、型を `Alloc` とし、引数列を `v1, v2, ..., vN`、その型を `V1, V2, ..., VN` とすると

- `T` がアロケータを利用しない場合（`uses_allocator<T, Alloc>::value == false`かつ、`is_constructible<T, V1, V2, ..., VN>::value == true`ならば）
  `obj(v1, v2, ..., vN);` の形でコンストラクタを呼び出す。

- `T` がアロケータを利用し、アロケータをコンストラクタ引数の先頭で受け取る場合（`uses_allocator<T, Alloc>::value == true`かつ、`is_constructible<T, allocator_arg_t, Alloc, V1, V2, ..., VN>::value == true`ならば）
  `obj(allocator_arg, alloc, v1, v2, ..., vN);` の形でコンストラクタを呼び出す。

- `T` がアロケータを利用し、アロケータをコンストラクタ引数の末尾で受け取る場合（`uses_allocator<T, Alloc>::value == true`かつ、`is_constructible<T, V1, V2, ..., VN, Alloc>::value == true`ならば）
  `obj(v1, v2, ..., vN, alloc);` の形でコンストラクタを呼び出す。

- それ以外の場合、要求された構築はill-formedである。

すなわち、構築したい型がアロケータを利用するならば引数とアロケータを適切な順序でコンストラクタに与えて呼び出し、利用しないならば通常のコンストラクタ呼び出しを行うような構築方法である。

更に上記に加え C++20 以降では、構築する対象の型 `T` が `pair` の特殊化だった場合には、当該 `pair` のそれぞれの要素に対して再帰的に上記の構築方法を適用することが規定された。

## 備考

- 本型トレイツは、主にスコープアロケータモデルを採用するアロケータで使用されることを意図している。
  標準ライブラリでは、`scoped_allocator_adaptor`、`polymorphic_allocator` クラステンプレートで使用されている。
- 標準ライブラリで提供されるいくつかの型は本型トレイツの特殊化を提供している。（`tuple`、`promise`、各種コンテナアダプタ等）
- `pair` は `tuple` と同列の機能と考えられるが、本型トレイツの特殊化を提供していない。このため、標準ライブラリで提供されるスコープアロケータモデルを採用したアロケータでは C++17 までは独自に `pair` の各要素に対して uses-allocator 構築を適用している（ただし、ネストした `pair` の要素に対してはアロケータは伝播されない）。
  スコープアロケータモデルを採用したアロケータを自作する場合には、同様の対応を行う方が良いだろう。
  なお、C++20 で `pair` に対する特殊対応を含めた uses-allocator 構築サポートのためのユーティリティ関数が追加されたため、以前に比べて容易に uses-allocator 構築への対応が可能となった。

## 例

    #include <iostream>
    #include <memory>

    template <class T, class Allocator = std::allocator<T>>
    struct X {
      T x_;
      Allocator alloc_;
    public:
      using allocator_type = Allocator;

      X(std::allocator_arg_t, Allocator alloc, T x)
        : alloc_(alloc), x_(x) {}
    };

    int main()
    {
      const bool result = std::uses_allocator<X<int>, std::allocator<int>>::value;
      static_assert(result, "should be true");
    }

### 出力

## バージョン

### 言語

- C++11

### 処理系

- Clang: 3.0 ✅
- GCC: 4.6.4 ✅
- ICC: ??
- Visual C++: 2012 ✅, 2013 ✅

## 関連項目

- `scoped_allocator_adaptor`
- `polymorphic_allocator`
- `tuple`
- `promise`
- `uses_allocator_construction_args`
- `make_obj_using_allocator`
- `uninitialized_construct_using_allocator`

## 参照

- P0006R0 Adopt Type Traits Variable Templates from Library Fundamentals TS for C++17
- P0591R4 Utility functions to implement uses-allocator construction