2017-01-01 21 views
1

私はdeleterでunique_ptrを使いたいと思います。 私のdeleterで私のunique_ptrがdefault_ptrと完全に互換性があるようにしたいです。std :: unique_ptr、カスタムディテクタと型変更

私はそのようにした:

template <typename T> 
struct QObjectDeleteLaterDeletor : 
     public std::default_delete<T> 
{ 
    void operator()(T *p) 
    { 
     p->deleteLater(); 
    } 
}; 

template <typename T, class... Args> 
std::unique_ptr<T> qtMakeUniqueSpecial(Args&&... args) 
{ 
    return std::unique_ptr<T>(
       new T(std::forward<Args>(args)...), 
       QObjectDeleteLaterDeletor<T>()); 
} 

これはコンパイルしますが、動作しません。私のカスタムディレクターは無視され、デフォルトのものが代わりに使用されました。

私はそのようなことを行うことが可能であることを、このすべてを必要とする:

auto ptr1 = qtMakeUniqueSpecial<MyObject>(); 
std::unique_ptr<MyObject> ptr2; 
ptr2 = std::move(ptr1); 

(つまり今でもptr1.resetに注意してください)は、標準的な削除手段ではなく、私のいずれかを呼び出すことにつながります。

それは可能ですか?

+1

しかし、移動後、 'ptr1'はデータへのポインタを持ちません。 "削除"への移動後に 'ptr1'で' reset'を呼び出すことは意味がありません。あなたは[最小限の、完全で、証明可能な例](http://stackoverflow.com/help/mcve)を作成して私たちを見せてください。また、あなたのdeleterが呼び出されないことをあなたがどのように知っているかを教えてください。*デフォルトはです。 –

+2

いいえ、あなたがしていることはあなたのファンシーデリターを 'default_delete'にスライスしているだけです。 –

+0

もちろん、移動前にリセットを呼びます。最小限の例は疑問です。 –

答えて

1

あなたは2番目のテンプレート引数Deleterを持って

namespace std { 
    template<typename T, typename Deleter = default_delete<T> > 
    class unique_ptr; 
} 

を使用しようとしています。これを指定しないと、デフォルトはstd::default_delete<T>になります。それはコンストラクタが期待するものですので、あなたのコード

std::unique_ptr<T>(new T(std::forward<Args>(args)...), 
        QObjectDeleteLaterDeletor<T>()); 

は、constructor of std::unique_ptr<T>からconst std::default_delete<T>&を渡します。破棄されると(またはメンバーreset()への呼び出し)、これが呼び出されます。

振る舞いが異なることに注意してください:デリータの2番目のテンプレート引数はありませんが、構築時にカスタムディターターが用意されています(これは型消去によって保存する必要があります。std::unique_ptrは避けてください)。

2

テンプレートの引数としてQObjectDeleteLaterDeletorを指定する必要があります。そうでない場合はstd::default_deleteが削除者として使用され、それはQObjectDeleteLaterDeletorからスライスコピーされます。あなたはptr2std::unique_ptr<MyObject>として宣言

template <typename T, class... Args> 
std::unique_ptr<T, QObjectDeleteLaterDeletor<T>> qtMakeUniqueSpecial(Args&&... args) 
{ 
    return std::unique_ptr<T, QObjectDeleteLaterDeletor<T>> (
       new T(std::forward<Args>(args)...), 
       QObjectDeleteLaterDeletor<T>()); 
} 

注意、そしてptr2std::default_deleteでポインタを破壊します。 ptr1とタイプの一致を宣言した場合は、auto ptr2 = std::move(ptr1);のようになります。

+0

いいえこれは私にとってはうまくいかないでしょう。私の質問をお読みください。 –

+0

私のタイプをstd :: unique_ptr にしたいと思います。 unique_ptr ではありません。 –

+0

shared_ptrで可能であり、unique_ptrでは不可能と思われます。 –

関連する問題