次の方法で共有


ATL コピー ポリシー クラス

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

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 を使用してデータを初期化し、コピーしてデータをコピーし、破棄してデータを解放します。 初期化、コピー、および破棄の正確な意味は、コピー ポリシー クラスのドメインであり、関係するデータ型によって異なります。

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

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

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

標準実装

ATL には、 _Copy_CopyInterface テンプレート クラスの形式で 2 つのコピー ポリシー クラスが用意されています。

  • _Copy クラスは、DestinationTypeSourceType の両方を指定する単一のテンプレート パラメーターのみを提供するため、(データ型間の変換ではなく) 同種のコピーのみを許可します。 このテンプレートの一般的な実装には、初期化コードや破棄コードが含まれており、 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::strings: 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 サンプル