次の方法で共有


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 には、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::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、およびユーザー設定の [コピー ポリシー クラスを示します

概念

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