名前空間
変種
操作

名前付き要件: Allocator

提供: cppreference.com
< cpp‎ | named req
 
 
名前付き要件
 

オブジェクトのアクセス、アドレス取得、確保、解放、構築、破棄に対する戦略をカプセル化します。

std::stringstd::vector、および std::array を除くすべてコンテナから、 std::shared_ptrstd::function まで、記憶域を確保したり解放したりする必要があることがあるすべての標準ライブラリのコンポーネントは Allocator を通してそれを行います。 Allocator は以下の要件を満たすクラス型のオブジェクトです。

いくつかの要件はオプショナルです。 テンプレート std::allocator_traits はすべてのオプショナルな要件に対するデフォルトの実装を提供し、すべての標準ライブラリのコンテナおよびその他のアロケータ対応クラスは直接ではなく std::allocator_traits を通してアロケータにアクセスします。

目次

[編集] 要件

  • cv 修飾されていないオブジェクト型 T
  • T 型に対する AllocatorA
  • A 型のオブジェクト a
  • 何らかの cv 修飾されていないオブジェクト型 U のための (A を rebind することによって取得された) 対応する AllocatorB
  • B 型のオブジェクト b
  • allocator_traits<A>::allocate() を呼ぶことによって取得された allocator_traits<A>::pointer 型の値 ptr
  • ptr からの変換によって取得された allocator_traits<A>::const_pointer 型の値 cptr
  • ptr からの変換によって取得された allocator_traits<A>::void_pointer 型の値 vptr
  • cptr からの、または vptr からの変換によって取得された allocator_traits<A>::const_void_pointer 型の値 cvptr
  • 何らかの cv 修飾されていないオブジェクト型 X への逆参照可能なポインタ xptr
  • *ptr によって取得された T 型の左辺値 r
  • allocator_traits<A>::size_type 型の値 n

が与えられたとき、

要件 戻り値の型
A::pointer (オプション) NullablePointerRandomAccessIterator および ContiguousIterator を満たす。 (下のファンシーポインタを参照)
A::const_pointer (オプション) A::pointerA::const_pointer に変換可能である。 NullablePointerRandomAccessIterator および ContiguousIterator を満たす。
A::void_pointer (オプション) A::pointerA::void_pointer に変換可能である。

B::void_pointerA::void_pointer が同じ型である。 NullablePointer を満たす。

A::const_void_pointer (オプション) A::pointerA::const_pointer および A::void_pointerA::const_void_pointer に変換可能である。

B::const_void_pointerA::const_void_pointer が同じ型である。 NullablePointer を満たす。

A::value_type T
A::size_type (オプション) A::size_type が確保可能な最も大きなオブジェクト A のサイズを表現できる。 符号なし整数型
A::difference_type (オプション) A::difference_typeA によって確保されたオブジェクトを指す任意の2つのポインタの差を表現できる。 符号なし整数型
A::template rebind<U>::other (オプション)[1] 任意の U について B::template rebind<T>::otherA である。 B
*ptr T&
*cptr *cptr*ptr が同じオブジェクトを識別する。 const T&
ptr->m (*ptr).m が well-defined であれば、 (*ptr).m と同じ。 T::m の型
cptr->m (*cptr).m が well-defined であれば、 (*cptr).m と同じ。 T::m の型
static_cast<A::pointer>(vptr) static_cast<A::pointer>(vptr) == ptr A::pointer
static_cast<A::const_pointer>(cvptr) static_cast<A::const_pointer>(cvptr) == cptr A::const_pointer
std::pointer_traits<A::pointer>::pointer_to(r) A::pointer
a.allocate(n) T 型のオブジェクト n 個のために適した記憶域を確保するが、それらを構築はしない。

例外を投げても構わない。

A::pointer
a.allocate(n, cvptr) (オプション) a.allocate(n) と同じであるが、局所性を補助するために cvptr (a.allocate() または nullptr_t から取得したポインタ) を未規定の方法で使用しても構わない。 A::pointer
a.deallocate(ptr, n) ptr の指す記憶域を解放する。 ptrallocate の以前の呼び出しによって返された値でなければならず、 deallocate の呼び出しを挟むことによって無効化されていてはならない。

nallocate に以前渡した値と一致しなければならない。 例外を投げない。

(未使用)
a.max_size() (オプション) A::allocate() に渡せる最も大きな値。 A::size_type
a1 == a2 アロケータ a1 によって確保された記憶域が a2 を通して解放できる場合にのみ true を返す。 反射律、対称律、推移律を確立する。 例外を投げない。 bool
a1 != a2 !(a1==a2) と同じ。 bool
A a1(a)

A a1 = a

a1 == a であるような a1 をコピー構築する。 例外を投げない。 (ノート: すべての AllocatorCopyConstructible も満たします)
A a(b) B(a)==b かつ A(b)==a であるような a を構築する。 例外を投げない。 (ノート: これは、 rebind によって関係を持つすべてのアロケータがメモリプールなどのお互いのリソースを管理することを暗黙に示します)
A a1(std::move(a))

A a1 = std::move(a)

a の以前の値と等しくなるような a1 を構築する。 例外を投げない。 a の値は変更されず、 a1 == a となる。 (C++20およびそれ以降)
A a(std::move(b)) A(b) の以前の値と等しくなるような a を構築する。 例外を投げない。
a.construct(xptr, args) (オプション) コンストラクタの引数として args を使用して、 xptr の指すアドレスにある以前に確保された記憶域に X 型のオブジェクトを構築する。
a.destroy(xptr) (オプション) xptr の指す X 型のオブジェクトを破棄するが、いかなる記憶域も解放はしない。
a.select_on_container_copy_construction() (オプション) 現在 a を使用しているコンテナからコピー構築されたコンテナによって使用されるための A のインスタンスを提供する。 通常、 a のコピーかデフォルト構築された A() のいずれかを返します。 A
A::propagate_on_container_copy_assignment (オプション) A のアロケータを使用するコンテナがコピー代入されたときにアロケータをコピーする必要がある場合 true。 ソースコンテナとターゲットコンテナのアロケータが等しくない場合、コピー代入は要素 (およびアロケータ) をコピーする前に古いアロケータを使用してターゲットのメモリを解放し、それから新しいアロケータを使用して確保する必要があることに注意してください。 std::true_type または std::false_type またはそれらの派生
A::propagate_on_container_move_assignment (オプション) A のアロケータを使用するコンテナがムーブ代入されたときにアロケータをムーブする必要がある場合 true。 このメンバが false でソースコンテナとターゲットコンテナのアロケータが等しくない場合、ムーブ代入はソースメモリの所有権を取ることはできず、自身のメモリを必要に応じてリサイズし、要素を個別にムーブ代入またはムーブ構築しなければなりません。 std::true_type または std::false_type またはそれらの派生
A::propagate_on_container_swap (オプション) A のアロケータを使用するコンテナがスワップされたとき、アロケータをスワップする必要がある場合 true。 このメンバが false で2つのコンテナのアロケータが等しくない場合、コンテナのスワップの動作は未定義です。 std::true_type または std::false_type またはそれらの派生
A::is_always_equal (C++17およびそれ以降) (オプション) A の任意の2つのアロケータが常に等しい場合は true。 提供されない場合、 std::allocator_traits によりデフォルトで std::is_empty<A>::type と等しくなります。 std::true_type または std::false_type またはそれらの派生

注釈:

  1. rebind はこのアロケータが SomeAllocator<T, Args> 形式のテンプレートである場合にのみオプショナルです (std::allocator_traits によって提供されます)。 ただし Args はゼロ個以上の追加のテンプレート型引数です。

さらに、型 AAllocator を満たすためには、

  • A::propagate_on_container_copy_assignment::valuetrue であれば、 ACopyAssignable を満たさなければならず、コピー操作は例外を投げてはなりません。
  • A::propagate_on_container_move_assignment::valuetrue であれば、 AMoveAssignable を満たさなければならず、ムーブ操作は例外を投げてはなりません。
  • A::propagate_on_container_swap::valuetrue であれば、 A の左辺値は Swappable でなければならず、スワップ操作は例外を投げてはなりません。
(C++17およびそれ以降)

また、

  • X::void_pointerX::const_void_pointerX::pointer または X::const_pointer 型の (異なるかもしれない) オブジェクト x1, x2

が与えられたとき、 x1 および x2X::const_pointer 型の対応する2つのオブジェクト px1 および px2 に、これら4つの型のみを使用した一連の static_casts を用いて明示的に変換でき、式 px1 == px2 が true に評価される場合に限り、 x1 と x2 は同等に評価されるポインタ値です。

また、

  • X::void_pointer 型のオブジェクト w1, w2

が与えられたとき、式 w1 == w2 および w1 != w2 について、いずれかまたは両方のオブジェクトを意味を変えずに X::const_void_pointer 型の同等に評価されるオブジェクトに置き換えることができます。

また、

  • X::pointer 型のオブジェクト p1, p2

が与えられたとき、式 p1 == p2, p1 != p2, p1 < p2 p1 <= p2, p1 >= p2, p1 > p2, p1 - p2} について、いずれかまたは両方のオブジェクトを意味を変えずに X::const_pointer 型の同等に評価されるオブジェクトに置き換えることができます。

上の要件により、 Container のイテレータと const_iterator の比較が可能となります。

(C++14およびそれ以降)


アロケータの完全性の要件

T が完全型かどうかにかかわらず、以下の両方が真であれば、型 T のためのアロケータ型 X はさらにアロケータの完全性の要件を満たします。

  • X が完全型である。
  • value_type を除いた std::allocator_traits<X> のすべてのメンバ型が完全型である。
(C++17およびそれ以降)

[編集] ファンシーポインタ

メンバ型 pointer が生のポインタ型でないとき、それは一般的に「ファンシーポインタ」と呼ばれます。 そのようなポインタはセグメント化されたメモリアーキテクチャをサポートするために導入され、今日では生のポインタによってアクセスされる均質な仮想アドレス空間とは異なるアドレス空間に確保されたオブジェクトにアクセスするために使用されます。 ファンシーポインタの例としては、 std::set のようなノードベースのデータ構造を、共有メモリや、各プロセス内の異なるアドレスにマップされたメモリマップドファイルに確保することを可能とする、マップされたアドレスに依存しないポインタ boost::interprocess::offset_ptr があります。 ファンシーポインタは、クラステンプレート std::pointer_traits を通して、それを提供するアロケータとは独立に、使用することができます。

[編集] 標準ライブラリ

以下の標準ライブラリのコンポーネントは Allocator の要件を満たします。

デフォルトのアロケータ
(クラステンプレート) [edit]
多段コンテナのための多段アロケータを実装します
(クラステンプレート) [edit]
構築時に指定された std::memory_resource をベースとした実行時ポリモーフィズムをサポートするアロケータ
(クラステンプレート) [edit]

[編集]

C++11 のアロケータ。 ただし C++20 のスタイルにマッチさせるために [[nodiscard]] が追加されています。

#include <cstdlib>
#include <new>
template <class T>
struct Mallocator {
  typedef T value_type;
  Mallocator() = default;
  template <class U> constexpr Mallocator(const Mallocator<U>&) noexcept {}
  [[nodiscard]] T* allocate(std::size_t n) {
    if(n > std::size_t(-1) / sizeof(T)) throw std::bad_alloc();
    if(auto p = static_cast<T*>(std::malloc(n*sizeof(T)))) return p;
    throw std::bad_alloc();
  }
  void deallocate(T* p, std::size_t) noexcept { std::free(p); }
};
template <class T, class U>
bool operator==(const Mallocator<T>&, const Mallocator<U>&) { return true; }
template <class T, class U>
bool operator!=(const Mallocator<T>&, const Mallocator<U>&) { return false; }