Rogue Wave バナー
前へマニュアルの先頭へ目次索引次へ

15.3 ユーザー独自のアロケータの構築

ユーザー独自の allocator を定義することは、比較的単純なプロセスです。標準 C++ ライブラリには、型と関数で構成される特定のインタフェースが記述されています。標準と準拠するアロケータは、これらのメンバー関数と型の構文要求に準拠している必要があります。また、標準 C++ ライブラリは、構文の一部をアロケータ型に指定しています。

標準 C++ ライブラリのアロケータインタフェースは、メンバーテンプレートに深く依存しています。このマニュアルの執筆時点では、コンパイラの多くが、メンバー関数テンプレートもメンバークラステンプレートもまだサポートしていません。このため、標準アロケータはまだ実装することができません。Rogue Wave の標準 C++ ライブラリの実装によって、選択不可のコンパイラ機能を要求せずに、標準インタフェースのほとんどの機能を提供する代替アロケータインタフェースが提供されます。このインタフェースは、標準インタフェースとは多少異なり、他のベンダーの標準 C++ ライブラリバージョンでは有効に機能しません。

アロケータを定義したり、コンテナを実装するときは、標準インタフェースとRogue Wave インタフェースを両方指定することを推奨します。これにより、アロケータをただちに使用できると共に、標準インタフェースがコンパイラに使用可能になり次第、標準の利点を活用することができます。

この章の以降の節では、標準 C++ ライブラリアロケータの要求、Rogue Wave の代替アロケータの要求、2 つのインタフェースを同じコードでどのようにサポートするかを指定する方法について説明します。

15.3.1 標準アロケータインタフェースの使用方法

標準 C++ ライブラリアロケータ仕様に準拠する allocator は、以下のインタフェースを備えている必要があります。この例では、ユーザー独自のアロケータ名のプレースホルダとして my_allocator を使用します。

このインタフェースでは、各ポインタ型は void* へ変換する必要があります。結果として得られる void* は、コンストラクタまたはデストラクタに、また適当な B、すなわち B::deallocate() 用の B<void>::pointer への変換に this 値として使用できなければなりません。

rebind メンバーを使用して、コンテナは、テンプレートパラメータとして提供されるアロケータ型から任意の型のアロケータを作成することができます。たとえば、list コンテナは、デフォルトで allocator<T> を作成しますが、listlist_nodeT の割り当てが必要となる場合もあります。コンテナは、T へのアロケータから、この場合テンプレートパラメータ Allocator である list_node へのアロケータを以下のように構築することができます。

以下は、標準 C++ ライブラリの allocator が定義する必要のあるメンバー関数の記述です。

my_allocator();
template <class U>
my_allocator(const my_allocator<U>&);
template <class U>
operator=(const my_allocator<U>&);

~my_allocator();
pointer address(reference r) const;
const_pointer address(const_reference r)
                        const;
pointer allocate(size_type n, const_pointer hint=0);
void 
deallocate(pointer);
size_type 
max_size();
void 
construct(pointer p, const T& val);
void 
destroy(pointer p);

以下は、標準 C++ ライブラリの allocator が定義する必要のある非メンバー関数の記述です。

template <class T>
my_allocator::pointer 
operator new(my_allocator::size_type, my_allocator&);
template <class T, class U>
bool 
operator==(const my_allocator<T>& a, 
           const my_allocator<U>& b);
template <class T, class U>
bool 
operator!=(const my_allocator<T>& a, 
           const my_allocator<U>& b);

15.3.2 Rogue Wave の代替インタフェースの使用方法

Rogue Wave では、クラステンプレートとメンバー関数テンプレートのどちらもサポートしないコンパイラに、代替アロケータインタフェースを提供します。

このインタフェースでは、クラス allocator_interface がすべての型と型付き関数を提供します。メモリーは、Allocator テンプレートパラメータによって提供されるクラスを使用して、未使用バイトとして割り振ります。 allocator_interface 内の関数は、ポインタ値を返す前に適宜キャストされます。複数の allocator_interface オブジェクトを単一の allocator に添付できるため、関連する型の数にかかわらず、1 つの allocator でコンテナのすべての記憶を割り当てることができます。実際の制約の 1 つに、ポインタと参照が型 T* および T& としてハードコード化されることがあります (標準インタフェースでは、これは implementation_defined となります)。コンパイラがメンバーテンプレートではなく部分特殊化をサポートする場合、これを使用してアロケータ型に allocator_interface を特殊化して、この制約に対処することができます。

代替インタフェースを基に allocator を実装するには、次のようにラベル付きクラス my_allocator を指定します。

標準コンテナがクラスをどのように使用するかを示すため、allocator_interface クラスの完全実装リストも含めました。コンテナが代替インタフェースを使用する方法については、第 16 章で詳しく説明します。

15.3.3 両インタフェースをサポートする方法

Rogue Wave では、標準 C++ ライブラリのアロケータインタフェースと、代替インタフェースの両方をサポートするコンテナを実装することを強く推奨します。両方のインタフェースがサポートされていれば、アロケータをすぐに使用でき、また標準アロケータインタフェースがコンパイラに使用可能になったときに標準の利点を活用することができます。

アロケータインタフェースの両バージョンを実装するには、コンテナに、標準インタフェースが使用可能かどうかを判断する機構が必要となります。Rogue Wave は、標準アロケータが使用可能かどうかを定義するためのマクロ _RWSTD_ALLOCATORstdcomp.h に用意しています。_RWSTD_ALLOCATOR によって true と評価されれば、コンパイラは標準 C++ ライブラリアロケータを処理することができます。それ以外の場合は、代替アロケータを使用しなければなりません。

_RWSTD_ALLOCATOR を最初に使用するのは、インタフェースを反映させるためにコンテナが使用しなければならない型名を決定するときです。この場合は、以下と同じコードをコンテナクラス定義に挿入します。

ここでは、T に関連する型に rebind を使用していることに注意してください。この場合、アロケータがたとえば vector<int, allocator<void> > など、別の型のアロケータテンプレートパラメータでインスタンス化されても、コンテナが有効であることが保証されるため、これが最も安全な方法です。これにより、Rogue Wave のコンテナは安定したものとなっています。また、value_allocatornode_allocator の 2 つの型のアロケータが提供されることも重要です。実際のアロケータをコンテナにアセンブルすることが必要となるのは、おそらくアロケータが必要になったときでしょう。この例では、どのインタフェースが使用されているかにかかわらず、Tallocator::allocate 呼び出し機構は次のようになります。

この呼び出しで、テンプレートコピーコンストラクタを使用して適当なアロケータを作成し、次に、その allocatorallocate を呼び出します。このアロケータの使用結果の例として、アロケータに保存されていた状態が参照によってコピーコンストラクタに渡され、その結果、この状態は既存のアロケータオブジェクトに保存され、このオブジェクトがコンテナのコンストラクタに渡されます。



前へマニュアルの先頭へ目次索引次へ
Copyright (c) 1998, Rogue Wave Software, Inc.
このマニュアルに関する誤りのご指摘やご質問は、電子メールにてお送りください。
OEM リリース, 1998 年 6 月