ATL のコピー ポリシー クラス

更新 : 2007 年 11 月

コピー ポリシー クラスとは、データの初期化、コピー、および削除に使用するユーティリティ クラスです。コピー ポリシー クラスを使用すると、どのようなデータ型に対してもコピー形式を定義できます。また、異なるデータ型間での変換も定義できます。

ATL は、次のテンプレートの実装にコピー ポリシー クラスを使用します。

データのコピーや変換に必要な情報をコピー ポリシー クラスにカプセル化し、このクラスをテンプレートの引数として渡すことができます。この方法によって、コピー ポリシー クラスを何度でも再利用できます。たとえば、どのデータ型を使用してコレクションを実装する必要がある場合でも、適切なコピー ポリシーを提供するだけで済みます。コレクションを実装するコードを触る必要は一切ありません。

定義

定義により、次の静的関数を提供するクラスは、すべてコピー ポリシー クラスです。

static void init(DestinationType* p);

static HRESULT copy(DestinationType* pTo, const SourceType* pFrom);

static void destroy(DestinationType* p);

DestinationType と SourceType の各型は、各コピー ポリシーの任意のデータ型に置き換えることができます。

td6kz9x0.alert_note(ja-jp,VS.90).gifメモ :

コピー ポリシー クラスはどのデータ型に対しても定義できますが、ATL コードの中で使用する場合は、意味のある型に限定されます。たとえば、ATL のコレクションまたは列挙子の実装でコピー ポリシー クラスを使用する場合は、DestinationType が、COM インターフェイス メソッドのパラメータとして使用できる型である必要があります。

init はデータの初期化に、copy はデータのコピーに、destroy はデータの解放に使用します。初期化、コピー、および消滅の正確な意味は、コピー ポリシー クラスで定義されており、関係するデータ型によって異なります。

コピー ポリシー クラスを使用および実装するには、次の 2 つの条件があります。

  • copy の最初のパラメータは、init によって初期化されたデータを指すポインタだけを受け取る必要があります。

  • destroy は、init によって初期化されたか、または copy によってコピーされたデータを指すポインタだけを受け取る必要があります。

標準的な実装

ATL には、_Copy テンプレート クラスおよび _CopyInterface テンプレート クラスという 2 つのコピー ポリシー クラスが用意されています。

  • _Copy クラスでは、DestinationType と SourceType の両方を指定するテンプレート パラメータが 1 つしかないため、データ型間での変換を伴わない同種間コピーだけを行うことができます。このテンプレートの汎用実装は、初期化コードや消滅コードを含まず、memcpy を使用してデータをコピーします。ATL には、VARIANTLPOLESTROLEVERB、および 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::string からのコピーを行うために特化された 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、およびカスタム コピー ポリシーの各クラスの例

概念

STL ベースのコレクションの実装