QScopedPointer
は、移動セマンティクスをサポートしていないため、unique_ptr
より厳密に弱いです。
それ以外の点では、その機能は非常に似ています。
移動セマンティクスは非常に便利で、間違って問題を引き起こすために誤って使用することは非常にまれです。だから彼らは無害から(より典型的に)役に立つものまで。
QScopedPointer
は、既存のコードベースとの相互運用性のために使用する必要があります。それらがどれほど似ているかを考慮すると、アダプタはかなり簡単になります。
適応する必要がない場合は、unique_ptr
を使用してください。
ここでは、適応について説明します。
トリッキーな部分は、QScopedPointer
の2番目のパラメータです。これは、大雑把には、第2パラメータunique_ptr
に相当します。
unique_ptr
ステートフルレターが許可されています。 QScopedPointer
ではそうではありません。
static void cleanup(T* pointer)
はかなり一対一でunique_ptr
で
void operator()(T* pointer)const
に対応しています。したがって:
template<class QDelete>
struct std_deleter {
template<class T>
void operator()(T* target) const {
QDelete::cleanup(target);
}
};
は、Qt deleterをstd deleterにマップします。
template<class Std_deleter>
struct Qt_deleter {
template<class T>
static void cleanup(T* target) {
static_assert(std::is_empty<Std_deleter>{}, "Only works with stateless deleters");
Std_deleter{}(target);
}
};
私たちが今変換することができます:
あなたが
QScopedPointer
を使用したい唯一の理由についてはカバーしてい
template<class T, class D>
QScopedPointer<T, Qt_deleter<D>>
to_qt(std::unique_ptr<T, D>&& src) {
return src.release();
}
template<class T, class D>
QScopedPointer<T, Qt_deleter<D>>
to_qt(std::unique_ptr<T[], D>&& src) {
return src.release();
}
template<class T>
QScopedPointer<T>
to_qt(std::unique_ptr<T>&& src) {
return src.release();
}
template<class T>
QScopedPointer<T, QScopedPointerArrayDeleter>
to_qt(std::unique_ptr<T[]>&& src) {
return src.release();
}
template<
class T, class D, class R=std::unique_ptr<T, std_deleter<D> >
>
to_std(QScopedPointer<T, D>&& src) {
return R(src.take()); // must be explicit
}
template<class T, class R=std::unique_ptr<T>>
to_std(QScopedPointer<T>&& src) {
return R(src.take()); // must be explicit
}
template<class T, class R=std::unique_ptr<T[]>>
to_std(QScopedPointer<T,QScopedPointerArrayDeleter >&& src) {
return R(src.take()); // must be explicit
}
他の方法は、ステートレスであることデリータによって制限されています。いくつかのコーナーケースがあります。デフォルトのデリーターQScopedPointer
はデフォルトのstd::unique_ptr
に変換され、その逆もあります。
アレイの削除QScopedPointer
は、unique_ptr<T[]>
に変換する必要があります。逆の場合も同様です。
他のケースでは、私は単純に削除者をまとめます。理論的には、本当に素晴らしいトリックは、入ってくるDeleterが既にラップされていて、ラッピングを取り消しているかどうかを確認することですが、もしあなたのコードが多くのラウンドトリップを行っているのであれば、
私は 'std :: unique_ptr'を使用します。 – NathanOliver
私はQtスマートポインタの使用量を減らし、代わりに 'std :: shared_ptr'と' std :: unique_ptr'を使用するように移動しました。 – drescherjm
標準ライブラリのクラスと別のクラスのどちらかを選択するときは、魅力的な理由がない限り、常に標準ライブラリを選択します。そのような説得力のある理由の1つは、他のタイプを使用するコードとの相互運用性が必要な場合です。 –