次の方法で共有


ATL コピー ポリシー クラス

コピー ポリシー クラスは、データの初期化、コピー、および削除に使用されるユーティリティ クラスです。 コピー ポリシー クラスを使用すると、あらゆる型のデータのコピー セマンティクスを定義したり、異なるデータ型間の変換を定義したりすることができます。

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

テンプレート引数として渡すことができるコピー ポリシー クラスのデータをコピーまたは変換するために必要な情報をカプセル化することによって、ATL 開発者はこれらのクラスを非常に再利用しやすくなりました。 たとえば、任意のデータ型を使用してコレクションを実装する必要がある場合は、適切なコピー ポリシーを指定するだけで済みます。コレクションを実装するコードに触れる必要はありません。

Definition

定義上、次の静的関数を提供するクラスがコピー ポリシー クラスとなります。

static void init( DestinationType * p);

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

static void destroy( DestinationType * p);

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

Note

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

データを初期化する場合は init、データをコピーする場合は copy、データを解放する場合は destroy を使用します。 初期化、コピー、および破棄の正確な意味は、コピー ポリシー クラスの領域であり、関連するデータ型によって異なります。

コピー ポリシー クラスの使用と実装には、次の 2 つの要件があります。

  • copy の最初のパラメーターでは、以前に init を使用して初期化したデータへのポインターのみを受け取る必要があります。

  • destroy では、以前に init を使用して初期化したか、copy を使ってコピーしたデータへのポインターのみを受け取る必要があります。

標準実装

ATL では、_Copy および _CopyInterface テンプレート クラスの形式で 2 つのコピー ポリシー クラスが提供されます。

  • _Copy クラスの場合、DestinationTypeSourceType の両方を指定する 1 つのテンプレート パラメーターのみが提供されるため、(データ型間の変換ではなく) 同種のコピーのみが許可されます。 このテンプレートの汎用実装には、初期化または破棄コードは含まれておらず、memcpy を使用してデータをコピーします。 ATL では、VARIANT、LPOLESTR、OLEVERB、および CONNECTDATA データ型に対する _Copy の特殊化も提供されます。

  • _CopyInterface クラスでは、標準の COM 規則に従ってインターフェイス ポインターをコピーするための実装が提供されます。 ここでも、このクラスでは同種のコピーのみが許可されるため、単純な割り当てと AddRef の呼び出しを使用してコピーが実行されます。

カスタム実装

通常は、異種コピー (つまり、データ型間の変換) 用に独自のコピー ポリシー クラスを定義する必要があります。 カスタム コピー ポリシー クラスのいくつかの例については、ATLCollections サンプルのファイル VCUE_Copy.h および VCUE_CopyString.h を参照してください。 これらのファイルには、GenericCopyMapCopy という 2 つのテンプレート コピー ポリシー クラスに加え、さまざまなデータ型の GenericCopy の特殊化が多く含まれています。

GenericCopy

GenericCopy では、SourceTypeDestinationType をテンプレート引数として指定できます。 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 では、コピーされるデータは C++ 標準ライブラリスタイルのマップに格納されることが前提であるため、データが格納されるマップの型とターゲットの型を指定できます。 クラスの実装では、MapType クラスによって提供される typedef を使用して、ソース データの型を判断し、適切な GenericCopy クラスを呼び出すだけです。 このクラスの特殊化は必要ありません。

template <class MapType, class DestinationType = MapType::mapped_type>
class MapCopy
{
public :
   typedef DestinationType               destination_type;
   typedef typename MapType::value_type  source_type;
   
   typedef MapType                       map_type;
   typedef typename MapType::mapped_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

関連項目

C++ 標準ライブラリに基づくコレクションの実装
ATLCollections サンプル