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
クラスの場合、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::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