オブジェクトの破壊をキャプチャする必要がないため、ここでは実際には必要ありません。そのウィキペディアのページの例では、そのタイプのオブジェクトがいくつ存在するかの現在の合計が保持されていることに注意してください。そのため、CRTP には 2 つの便利な機能があります。
- これは基本クラスであるため、そのデストラクタが呼び出されます (メンバーもこれを実現します)。
- 派生クラス型でテンプレート化されているため、継承するクラスごとに個別のカウンターがあり、複数の継承を使用してそれぞれ独自の CRTP ベースを含める場合、階層内の異なるクラスを含め、各クラスに多くのコードを記述する必要はありません。
単一のクラスの各メンバーに一意の値が必要な場合は、スレッドセーフは別として、次のようにできます。
int get_id() {
static int counter = 0;
return ++counter;
}
class Address {
int addr;
public:
Address() : addr(get_id()) {}
};
CRTP の例に従って、追跡する複数のクラスがあり、それぞれに独自の ID スペースを持たせたい場合は、テンプレートget_id
化して引数として使用できます。Address
そして、このユース ケースでは、CRTP を使用した場合、データ メンバーaddr
をテンプレート ベース クラスに配置できます。これは、それを使用する各クラスの入力が少ないため、多くのクラスがある場合に役立ちます。
template <typename Derived>
class unique_addr {
protected:
int addr;
unique_addr() : addr(get_id<Derived>()) {}
};
class Address : public unique_addr<Address> {
};
class OtherAddress : public unique_addr<OtherAddress> {
};