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

履歴 編集

class template
<memory>

std::allocator_traits(C++11)

namespace std {
  template <class Alloc>
  struct allocator_traits;
}

概要

allocator_traitsは、アロケータクラスの機能に間接的にアクセスするためのインタフェースを提供するクラスである。

備考

このクラスはC++11から導入され、メモリアロケータを扱うクラス(たとえばコンテナ)は、アロケータクラスの機能に直接アクセスする従来の仕様から、allocator_traitsを介してアロケータにアクセスするように変更された。

allocator_traitsはアロケータに必要な機能の多くに対してデフォルト実装を用意しているため、この変更により、ユーザーが自作アロケータを作るのが容易になった。

静的メンバ関数

名前 説明 対応バージョン
allocate メモリを確保する C++11
deallocate メモリを解放する C++11
max_size 一度に確保可能なメモリの最大サイズを取得する C++11
construct 引数を元にインスタンスを構築する C++11
destroy インスタンスを破棄する C++11
select_on_container_copy_construction コンテナのコピー構築に使用するアロケータオブジェクトを取得する C++11

メンバ型

名前 説明 対応バージョン
allocator_type アロケータ型 Alloc C++11
value_type 要素の型 typename Alloc::value_type C++11
pointer 要素のポインタ型。
Allocがメンバ型pointerを持っていればそれを使用し、そうでなければvalue_type*を使用する。
C++11
const_pointer 読み取り専用の要素のポインタ型。
Allocがメンバ型const_pointerを持っていればそれを使用し、そうでなければpointer_traits<pointer>::rebind<const value_type>を使用する。
C++11
void_pointer voidのポインタ型。
Allocがメンバ型void_pointerを持っていればそれを使用し、そうでなければpointer_traits<pointer>::rebind<void>を使用する。
C++11
const_void_pointer 読み取り専用のvoidのポインタ型。
Allocがメンバ型const_void_pointerを持っていればそれを使用し、そうでなければpointer_traits<pointer>::rebind<const void>を使用する。
C++11
difference_type ポインタの差を表す符号付き整数型。
Allocがメンバ型difference_typeを持っていればそれを使用し、そうでなければpointer_traits<pointer>::difference_typeを使用する。
C++11
size_type 要素数を表す符号なし整数型。
Allocがメンバ型size_typeを持っていればそれを使用し、そうでなければmake_unsigned<difference_type>::typeを使用する。
C++11
propagate_on_container_copy_assignment コンテナのコピー代入時に、アロケータオブジェクトをコピー(伝播)するか否か。
Allocがメンバ型propagate_on_container_copy_assignmentを持っていればそれを使用し、そうでなければfalse_typeを使用する。
C++11
propagate_on_container_move_assignment コンテナのムーブ代入時に、アロケータオブジェクトをコピー(伝播)するか否か。
Allocがメンバ型propagate_on_container_move_assignmentを持っていればそれを使用し、そうでなければfalse_typeを使用する。
C++11
propagate_on_container_swap コンテナの交換時に、アロケータオブジェクトをコピー(伝播)するか否か。
Allocがメンバ型propagate_on_container_swapを持っていればそれを使用し、そうでなければfalse_typeを使用する。
C++11
is_always_equal Alloc::is_always_equalが存在する場合はAlloc::is_always_equal。それ以外の場合はis_empty<Alloc>::type C++17
rebind_alloc<U> Uを確保するようにアロケータ型を再束縛する。
Alloc::rebind<U>::otherが有効ならそれを使用し、そうでなければAlloc<U, Args>を使用する(ここで、Argsは0個以上の型引数で、AllocAlloc<T, Args>だった際のArgsである)。Allocがクラステンプレートでない場合、rebind_allocの使用は不適格となる。
C++11
rebind_traits<U> 再束縛した型Uに対するallocator_traitsallocator_traits<rebind_alloc<U>> C++11

基本的な使い方

#include <memory>

template <class T, class Alloc>
class MyVector {
  T* data_;
  std::size_t size_;
  Alloc alloc_;
public:
  MyVector(std::size_t size)
  {
    using traits = std::allocator_traits<Alloc>;

    size_ = size;

    // メモリを確保
    data_ = traits::allocate(alloc_, size);

    // 要素を構築
    for (std::size_t i = 0; i < size_; ++i) {
      traits::construct(alloc_, &data_[i]);
    }
  }

  ~MyVector()
  {
    using traits = std::allocator_traits<Alloc>;

    // 要素を破棄
    for (std::size_t i = 0; i < size_; ++i) {
      traits::destroy(alloc_, &data_[i]);
    }

    // メモリを解放
    traits::deallocate(alloc_, data_, size_);
  }
};

int main()
{
  MyVector<int, std::allocator<int>> v(3);
}

出力

rebind_allocの使用例

#include <iostream>
#include <memory>

template <class T>
struct node {
  T value;
  node<T>* next;
};

// 単方向リンクリストの実装
template <class T, class Alloc=std::allocator<T>>
class my_forward_list {
  // 実際にメモリ確保したいのはT型ではなくnode<T>型なので、
  // allocator<T>をallocator<node<T>>に置き換える
  using allocator_type = typename std::allocator_traits<
    Alloc
  >::template rebind_alloc<node<T>>;

  using allocator_traits_type =
    std::allocator_traits<allocator_type>;

  node<T>* head_ = nullptr;
  allocator_type alloc_;

public:
  ~my_forward_list() {
    node<T>* p = head_;
    while (p) {
      node<T>* next = p->next;

      allocator_traits_type::destroy(alloc_, p);
      allocator_traits_type::deallocate(alloc_, p, 1);

      p = next;
    }
  }

  void push_back(const T& x) {
    node<T>* new_node = allocator_traits_type::allocate(alloc_, 1);
    allocator_traits_type::construct(alloc_, new_node, node<T>{x, nullptr});

    if (!head_) {
      head_ = new_node;
    }
    else {
      node<T>* last_node = head_;
      while (true) {
        if (!last_node->next) {
          last_node->next = new_node;
          break;
        }
        last_node = last_node->next;
      }
    }
  }

  void print() {
    for (auto* p = head_; p; p = p->next) {
      std::cout << p->value << std::endl;
    }
  }
};

int main() {
  my_forward_list<int> ls;
  ls.push_back(3);
  ls.push_back(1);
  ls.push_back(4);
  ls.print();
}

出力

3
1
4

バージョン

言語

  • C++11

処理系

参照