Namespaces
Variants

C++ named requirements: Allocator

From cppreference.net
C++ named requirements

オブジェクトのアクセス/アドレッシング、割り当て/解放、および構築/破棄の戦略をカプセル化します。

ストレージの割り当てや解放が必要となる可能性があるすべての標準ライブラリコンポーネントは、 std::string std::vector 、およびすべてのコンテナ std::array を除く (C++11以降) および std::inplace_vector (C++26以降) )から std::shared_ptr および std::function (C++17まで) まで、これらはすべて アロケータ を通じて行われます:以下の要件を満たすクラス型のオブジェクトです。

多くのアロケータ要件の実装はオプションです。なぜなら全ての AllocatorAwareContainer はアロケータに間接的に std::allocator_traits を通じてアクセスし、 std::allocator_traits がそれらの要件に対するデフォルト実装を提供するためです。

目次

要件

与えられた

  • T 非const、非参照型 (C++11まで) 非constオブジェクト型 (C++11から) (C++17まで) CV修飾されないオブジェクト型 (C++17から)
  • A 、型 T に対する アロケータ 型、
  • a 、型 A のオブジェクト、
  • B 、何らかのCV修飾されないオブジェクト型 U に対する対応する アロケータ 型( A のリバインディングによって得られる)、
  • b 、型 B のオブジェクト、
  • p 、型 std:: allocator_traits < A > :: pointer の値( std:: allocator_traits < A > :: allocate ( ) の呼び出しによって得られる)、
  • cp 、型 std:: allocator_traits < A > :: const_pointer の値( p からの変換によって得られる)、
  • vp 、型 std:: allocator_traits < A > :: void_pointer の値( p からの変換によって得られる)、
  • cvp 、型 std:: allocator_traits < A > :: const_void_pointer の値( cp または vp からの変換によって得られる)、
  • xp 、何らかのCV修飾されないオブジェクト型 X へのデリファレンス可能なポインタ、
  • r 、式 * p によって得られる型 T の左辺値、
  • n 、型 std:: allocator_traits < A > :: size_type の値。
内部型
型ID エイリアス型 要件
A::pointer (オプション) (未指定) [1]
A::const_pointer (オプション) (未指定)
A::void_pointer (オプション) (未指定)
  • NullablePointer を満たす。
  • A::pointer A::void_pointer に変換可能。
  • B::void_pointer A::void_pointer は同じ型。
A::const_void_pointer (オプション) (未指定)
  • NullablePointer を満たす。
  • A::pointer A::const_pointer 、および A::void_pointer A::const_void_pointer に変換可能。
  • B::const_void_pointer A::const_void_pointer は同じ型。
A::value_type T
A::size_type (オプション) (未指定)
  • 符号なし整数型。
  • A が割り当て可能な最大オブジェクトのサイズを表現可能。
A::difference_type (オプション) (未指定)
  • 符号付き整数型。
  • A によって割り当てられたオブジェクトへの任意の2つのポインタの差を表現可能。
A::template rebind<U>::other
(オプション) [2]
B
  • 任意の U について、 B::template rebind<T>::other A となる。
ポインタに対する操作
戻り値の型 要件
* p T&
* cp const T & * cp * p が同じオブジェクトを指す。
p - > m (そのまま) ( * p ) . m と同じ。ただし ( * p ) . m が有効な場合。
cp - > m (そのまま) ( * cp ) . m と同じ。ただし ( * cp ) . m が有効な場合。
static_cast < A :: pointer > ( vp ) (そのまま) static_cast < A :: pointer > ( vp ) == p
static_cast < A :: const_pointer > ( cvp ) (そのまま) static_cast < A :: const_pointer > ( cvp ) == cp
std:: pointer_traits < A :: pointer > :: pointer_to ( r ) (そのまま)
ストレージと生存期間の操作
戻り値の型 要件
a. allocate ( n ) A::pointer T[n] 型の配列オブジェクトに適したストレージを確保し、配列を作成するが、配列要素は構築しない。例外を送出する可能性がある。 n == 0 の場合、戻り値は未規定。
a. allocate ( n, cvp ) (オプション) a. allocate ( n ) と同じだが、局所性を支援するために cvp ( nullptr または a. allocate ( ) から取得したポインタ)を未規定の方法で使用する可能性がある。
a. allocate_at_least ( n ) (オプション) (C++23以降) std:: allocation_result

< A :: pointer >

T[cnt] 型の配列オブジェクトに適したストレージを確保し、配列を作成するが、配列要素は構築しない。その後 { p, cnt } を返す。ここで p はストレージを指すポインタ、 cnt n 以上である。例外を送出する可能性がある。
a. deallocate ( p, n ) (使用しない) p が指すストレージを解放する。 p allocate または allocate_at_least (C++23以降) への以前の呼び出しで返された値であり、 deallocate への介在する呼び出しによって無効化されていないものでなければならない。 n は以前に allocate に渡された値と一致するか、 allocate_at_least を介して要求された要素数と返された要素数の間でなければならない(どちらかの境界と等しくてもよい) (C++23以降) 。例外を送出しない。
a. max_size ( ) (オプション) A::size_type A :: allocate ( ) に渡すことができる最大の値。
a. construct ( xp, args... ) (オプション) (使用しない) 以前に確保されたストレージ内の xp が指すアドレスに X 型のオブジェクトを構築する。 args... をコンストラクタ引数として使用する。
a. destroy ( xp ) (オプション) (使用しない) xp が指す X 型のオブジェクトを破棄するが、ストレージは解放しない。
インスタンス間の関係
戻り値型 要件
a1 == a2 bool
  • true は、アロケータ a1 によって割り当てられたストレージが a2 を通じて解放可能な場合にのみ。
  • 反射的、対称的、推移的関係を確立する。
  • 例外を投げない。
a1 ! = a2
  • ! ( a1 == a2 ) と同じ。
宣言 効果 要件
A a1 ( a ) a1 == a となるように a1 をコピー構築する。
(注:すべての Allocator CopyConstructible も満たす。)
  • 例外を投げない。
A a1 = a
A a ( b ) B ( a ) == b かつ A ( b ) == a となるように a を構築する。
(注:これは rebind によって関連するすべてのアロケータが互いのリソース(メモリプールなど)を維持することを意味する。)
  • 例外を投げない。
A a1 ( std :: move ( a ) ) a の以前の値と等しくなるように a1 を構築する。
  • 例外を投げない。
  • a の値は変更されず、 a1 == a
A a1 = std :: move ( a )
A a ( std :: move ( b ) ) A ( b ) の以前の値と等しくなるように a を構築する。
  • 例外を投げない。
型ID エイリアス型 要件
A::is_always_equal
(オプション)
std::true_type または std::false_type またはそれらから派生した型。
  • A の任意の2つのアロケータが常に等しいと比較される場合 true
  • (提供されない場合、 std::allocator_traits はこれを std:: is_empty < A > :: type にデフォルト設定する。)
コンテナ操作への影響
戻り値の型 説明
a. select_on_container_copy_construction ( )
(オプション)
A
  • 現在 a を使用しているコンテナからコピー構築されるコンテナで使用する A のインスタンスを提供する
  • (通常は a のコピーまたはデフォルト構築された A のいずれかを返す)
型ID エイリアス型 説明
A::propagate_on_container_copy_assignment
(オプション)
std::true_type または std::false_type またはそれらから派生した型
  • A のアロケータを使用するコンテナがコピー代入される際に、アロケータをコピーする必要がある場合は std::true_type またはそれから派生した型
  • このメンバが std::true_type またはそれから派生した型の場合、 A CopyAssignable を満たし、コピー操作は例外を投げてはならない
  • ソースとターゲットのコンテナのアロケータが等しくない場合、コピー代入は古いアロケータを使用してターゲットのメモリを解放し、新しいアロケータを使用してメモリを割り当てた後、要素(およびアロケータ)をコピーしなければならない
A::propagate_on_container_move_assignment
(オプション)
  • A のアロケータを使用するコンテナがムーブ代入される際に、アロケータをムーブする必要がある場合は std::true_type またはそれから派生した型
  • このメンバが std::true_type またはそれから派生した型の場合、 A MoveAssignable を満たし、ムーブ操作は例外を投げてはならない
  • このメンバが提供されていないか、 std::false_type から派生しておらず、ソースとターゲットのコンテナのアロケータが等しくない場合、ムーブ代入はソースのメモリの所有権を取得できず、要素を個別にムーブ代入またはムーブ構築し、必要に応じて自身のメモリをリサイズしなければならない
A::propagate_on_container_swap
(オプション)
  • A のアロケータを使用する2つのコンテナを交換する際に、アロケータを交換する必要がある場合は std::true_type またはそれから派生した型
  • このメンバが std::true_type またはそれから派生した型の場合、型 A Swappable を満たし、交換操作は例外を投げてはならない
  • このメンバが提供されていないか、 std::false_type から派生しておらず、2つのコンテナのアロケータが等しくない場合、コンテナ交換の動作は未定義である

注記:

  1. 詳細は以下の fancy pointers も参照のこと。
  2. rebind は、このアロケータが SomeAllocator<T, Args> という形式のテンプレートである場合にのみオプション( std::allocator_traits によって提供される)です。ここで Args は0個以上の追加のテンプレート型パラメータです。

与えられた

  • x1 および x2 、(異なる可能性もある)型 X::void_pointer X::const_void_pointer X::pointer 、または X::const_pointer のオブジェクト
その場合、 x1 x2 等価値の ポインタ値であるとは、 x1 x2 の両方が、これら4つの型のみを使用した static_cast のシーケンスを用いて、型 X::const_pointer の対応する2つのオブジェクト px1 px2 に明示的に変換可能であり、かつ式 px1 == px2 true と評価される場合に限ります。

与えられた

  • w1 w2 、型 X::void_pointer のオブジェクト
次に、式 w1 == w2 および w1 ! = w2 において、いずれか一方または両方のオブジェクトは、 等価な値を持つ X::const_void_pointer 型のオブジェクトで置き換えられても、セマンティクスに変化は生じない。

与えられた

  • p1 p2 、型 X::pointer のオブジェクト
次に、以下の式について p1 == p2 p1 ! = p2 p1 < p2 p1 <= p2 p1 >= p2 p1 > p2 p1 - p2 において、一方または両方のオブジェクトを 等価値を持つ X::const_pointer 型のオブジェクトで置き換えても、セマンティクスに変更は生じません。

上記の要件により、 Container iterator const_iterator を比較することが可能となります。

アロケータ完全性要件

T に対するアロケータ型 X は、 T が完全型であるかどうかに関わらず、以下の両方が真である場合に追加で アロケータ完全性要件 を満たす:

  • X が完全型である。
  • value_type を除く、 std:: allocator_traits < X > のすべてのメンバ型が完全型である。
(C++17以降)

ステートフルおよびステートレスアロケータ

すべての Allocator 型は、 stateful または stateless のいずれかです。一般的に、statefulアロケータ型は異なるメモリリソースを表す不等な値を持つことができますが、statelessアロケータ型は単一のメモリリソースを表します。

カスタムアロケータはステートレスである必要はないが、標準ライブラリでのステートフルアロケータの使用の可否と方法は実装定義である。不等なアロケータ値の使用は、実装がそのような使用をサポートしていない場合、実装定義の実行時エラーまたは未定義動作を引き起こす可能性がある。

(until C++11)

カスタムアロケータは状態を含むことができる。各コンテナまたは他のアロケータ対応オブジェクトは、提供されたアロケータのインスタンスを格納し、 std::allocator_traits を通じてアロケータの置換を制御する。

(since C++11)

ステートレスアロケータ型のインスタンスは常に等価として比較されます。ステートレスアロケータ型は通常、空のクラスとして実装され、 空の基底クラス最適化 に適しています。

メンバ型 is_always_equal は、 std::allocator_traits において、アロケータ型がステートレスかどうかを判定するために意図的に使用されます。

(C++11以降)

ファンシーポインタ

メンバ型 pointer が生ポインタ型でない場合、一般的に 「ファンシーポインタ」 と呼ばれます。このようなポインタはセグメント化メモリアーキテクチャをサポートするために導入され、現在では生ポインタがアクセスする均質な仮想アドレス空間とは異なるアドレス空間に割り当てられたオブジェクトにアクセスするために使用されます。ファンシーポインタの例として、マッピングアドレス非依存ポインタ boost::interprocess::offset_ptr があり、これにより std::set のようなノードベースのデータ構造を共有メモリや、プロセスごとに異なるアドレスにマップされたメモリマップトファイルに割り当てることが可能になります。ファンシーポインタは、それらを提供したアロケータとは独立して使用できます (クラステンプレート std::pointer_traits を通じて) (C++11以降) 関数 std::to_address を使用してファンシーポインタから生ポインタを取得できます。 (C++20以降)

標準ライブラリにおけるファンシーポインタおよびカスタマイズされたサイズ/異なる型の使用は条件付きでサポートされます。実装によっては、メンバ型 pointer const_pointer size_type 、および difference_type がそれぞれ value_type* const value_type * std::size_t 、および std::ptrdiff_t であることを要求する場合があります。

(C++11以前)

Concept

クエリオブジェクト std::get_allocator の定義のために、以下の説明専用コンセプトが定義される。

template < class Alloc >

concept /*simple-allocator*/ = requires ( Alloc alloc, std:: size_t n )
{
{ * alloc. allocate ( n ) } - > std:: same_as < typename Alloc :: value_type & > ;
{ alloc. deallocate ( alloc. allocate ( n ) , n ) } ;
} && std:: copy_constructible < Alloc >

&& std:: equality_comparable < Alloc > ;

説明専用コンセプト /*simple-allocator*/ は、 Allocator 要件の最小限の使用可能性制約を定義する。

(C++26以降)

標準ライブラリ

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

デフォルトアロケータ
(クラステンプレート)
マルチレベルコンテナ向けのマルチレベルアロケータを実装する
(クラステンプレート)
構築時に指定された std::pmr::memory_resource に基づいて実行時ポリモーフィズムをサポートするアロケータ
(クラステンプレート)

C++11アロケータの実装例を示します。 [[ nodiscard ]] はC++20スタイルに合わせて追加されています。

#include <cstdlib>
#include <iostream>
#include <limits>
#include <new>
#include <vector>
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::numeric_limits<std::size_t>::max() / sizeof(T))
            throw std::bad_array_new_length();
        if (auto p = static_cast<T*>(std::malloc(n * sizeof(T))))
        {
            report(p, n);
            return p;
        }
        throw std::bad_alloc();
    }
    void deallocate(T* p, std::size_t n) noexcept
    {
        report(p, n, 0);
        std::free(p);
    }
private:
    void report(T* p, std::size_t n, bool alloc = true) const
    {
        std::cout << (alloc ? "Alloc: " : "Dealloc: ") << sizeof(T) * n
                  << " bytes at " << std::hex << std::showbase
                  << reinterpret_cast<void*>(p) << std::dec << '\n';
    }
};
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; }
int main()
{
    std::vector<int, Mallocator<int>> v(8);
    v.push_back(42);
}

出力例:

Alloc: 32 bytes at 0x2020c20
Alloc: 64 bytes at 0x2023c60
Dealloc: 32 bytes at 0x2020c20
Dealloc: 64 bytes at 0x2023c60

不具合報告

以下の動作変更の欠陥報告書は、以前に公開されたC++規格に対して遡及的に適用されました。

DR 適用対象 公開時の動作 正しい動作
LWG 179 C++98 pointer const_pointer が互いに比較可能であることが
要求されていなかった
要求される
LWG 199 C++98 a.allocate(0) の戻り値が不明確だった 未規定
LWG 258
( N2436 )
C++98 アロケータ間の等価性関係が反射的、対称的、
推移的であることが要求されていなかった
反射的、対称的、推移的であることが要求される
LWG 274 C++98 T がconst修飾型または参照型である可能性があり、
std::allocator が不適格になる可能性があった [1]
これらの型を禁止
LWG 2016 C++11 アロケータのコピー、ムーブ、スワップ操作が
使用時に例外を送出する可能性があった
非例外送出が要求される
LWG 2081 C++98
C++11
アロケータがコピー代入(C++98)および
ムーブ代入(C++11)をサポートすることが要求されていなかった
要求される
LWG 2108 C++11 アロケータがステートレスであることを示す方法がなかった is_always_equal が提供される
LWG 2263 C++11 LWG issue 179 の解決がC++11で誤って削除され、
void_pointer const_void_pointer に一般化されていなかった
復元され一般化された
LWG 2447 C++11 T がvolatile修飾オブジェクト型である可能性があった これらの型を禁止
LWG 2593 C++11 アロケータからのムーブがその値を変更する可能性があった 変更が禁止される
P0593R6 C++98 allocate が割り当てたストレージに配列オブジェクトを
作成することが要求されていなかった
要求される
  1. std::allocator のメンバ型 reference const_reference は、それぞれ T& const T& として定義される。
    • T が参照型の場合、 reference const_reference は不正な形式となる(参照の参照は形成できないため。 参照畳み込み はC++11で導入された)。
    • T がconst修飾されている場合、 reference const_reference は同一となり、 address() のオーバーロードセットは不正な形式となる。