ATL のコピー ポリシー クラス
コピー ポリシー クラスとは、データの初期化、コピー、および削除に使用するユーティリティ クラスです。 コピー ポリシー クラスを使用すると、どのようなデータ型に対してもコピー形式を定義できます。また、異なるデータ型間での変換も定義できます。
ATL は、次のテンプレートの実装にコピー ポリシー クラスを使用します。
データのコピーや変換に必要な情報をコピー ポリシー クラスにカプセル化し、このクラスをテンプレートの引数として渡すことができます。この方法によって、コピー ポリシー クラスを何度でも再利用できます。 たとえば、どのデータ型を使用してコレクションを実装する必要がある場合でも、適切なコピー ポリシーを提供するだけで済みます。コレクションを実装するコードを触る必要は一切ありません。
定義
定義により、次の静的関数を提供するクラスは、すべてコピー ポリシー クラスです。
static void init(DestinationType* p);
static HRESULT copy(DestinationType* pTo, const SourceType* pFrom);
static void destroy(DestinationType* p);
DestinationType と SourceType の各型は、各コピー ポリシーの任意のデータ型に置き換えることができます。
注意
コピー ポリシー クラスはどのデータ型に対しても定義できますが、ATL コードの中で使用する場合は、意味のある型に限定されます。 たとえば、ATL のコレクションまたは列挙子の実装でコピー ポリシー クラスを使用する場合は、DestinationType が、COM インターフェイス メソッドのパラメーターとして使用できる型である必要があります。
init はデータの初期化に、copy はデータのコピーに、destroy はデータの解放に使用します。 初期化、コピー、および消滅の正確な意味は、コピー ポリシー クラスで定義されており、関係するデータ型によって異なります。
コピー ポリシー クラスを使用および実装するには、次の 2 つの条件があります。
copy の最初のパラメーターは、init によって初期化されたデータを指すポインターだけを受け取る必要があります。
destroy は、init によって初期化されたか、または copy によってコピーされたデータを指すポインターだけを受け取る必要があります。
標準的な実装
ATL には、_Copy テンプレート クラスおよび _CopyInterface テンプレート クラスという 2 つのコピー ポリシー クラスが用意されています。
_Copy クラスでは、DestinationType と SourceType の両方を指定するテンプレート パラメーターが 1 つしかないため、データ型間での変換を伴わない同種間コピーだけを行うことができます。 このテンプレートの汎用実装は、初期化コードや消滅コードを含まず、memcpy を使用してデータをコピーします。 ATL には、VARIANT、LPOLESTR、OLEVERB、および CONNECTDATA の各データ型用に特化した _Copy も用意されています。
_CopyInterface クラスには、標準の COM ルールに従ってインターフェイス ポインターをコピーするための実装が用意されています。 このクラスでも同種間コピーしか行うことができないため、単純な代入と AddRef の呼び出しによってコピーを行います。
カスタム実装
通常は、データ型間での変換を伴う異種間コピーを行うための、独自のコピー ポリシー クラスを定義する必要があります。 カスタムのコピー ポリシー クラスの例については、ATLCollections サンプルの VCUE_Copy.h ファイルと VCUE_CopyString.h ファイルを参照してください。 これらのファイルには、GenericCopy および MapCopy という 2 つのテンプレート コピー ポリシー クラスのほかに、データ型ごとに特化された GenericCopy クラスが含まれています。
GenericCopy
GenericCopy を使用すると、テンプレート引数として SourceType と DestinationType を指定できます。 VCUE_Copy.h の最も一般的な GenericCopy クラスを次に示します。
template <class DestinationType, class SourceType = DestinationType>
class GenericCopy
{
public :
typedef DestinationType destination_type;
typedef SourceType source_type;
static void init(destination_type* p)
{
_Copy<destination_type>::init(p);
}
static void destroy(destination_type* p)
{
_Copy<destination_type>::destroy(p);
}
static HRESULT copy(destination_type* pTo, const source_type* pFrom)
{
return _Copy<destination_type>::copy(pTo, const_cast<source_type*>(pFrom));
}
}; // class GenericCopy
VCUE_Copy.h ではこのクラスの次の特殊化も含まれます。GenericCopy<BSTR>, GenericCopy<VARIANT, BSTR>, GenericCopy<BSTR, VARIANT>. VCUE_CopyString.h からコピーするには、特殊化が含まれているstd::strings:GenericCopy<std::string>、GenericCopy<VARIANT, std::string>、および GenericCopy<BSTR, std::string>。 GenericCopy を独自に特化して拡張することもできます。
MapCopy
MapCopy は、コピーしたデータを STL 形式のマップに格納するものと見なします。このため、データを格納するマップの種類と、コピー先の型を指定できます。 クラスの実装では、MapType クラスで指定された typedef だけを使用して、コピー元データの型を判別し、適切な GenericCopy クラスを呼び出します。 このクラスを特化する必要はありません。
template <class MapType, class DestinationType = MapType::referent_type>
class MapCopy
{
public :
typedef DestinationType destination_type;
typedef typename MapType::value_type source_type;
typedef MapType map_type;
typedef typename MapType::referent_type pseudosource_type;
static void init(destination_type* p)
{
GenericCopy<destination_type, pseudosource_type>::init(p);
}
static void destroy(destination_type* p)
{
GenericCopy<destination_type, pseudosource_type>::destroy(p);
}
static HRESULT copy(destination_type* pTo, const source_type* pFrom)
{
return GenericCopy<destination_type, pseudosource_type>::copy(pTo, &(pFrom->second));
}
}; // class MapCopy
参照
処理手順
ATLCollections サンプル:ICollectionOnSTLImpl、CComEnumOnSTL、およびユーザー設定の [コピー ポリシー クラスを示します