コピー ポリシー クラスは、データの初期化、コピー、および削除に使用される ユーティリティ クラス です。 コピー ポリシー クラスを使用すると、任意の種類のデータのコピー セマンティクスを定義したり、異なるデータ型間の変換を定義したりできます。
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クラスは、DestinationTypeと SourceType の両方を指定する単一のテンプレート パラメーターのみを提供するため、(データ型間の変換ではなく) 同種のコピーのみを許可します。 このテンプレートの一般的な実装には、初期化コードや破棄コードが含まれており、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::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