2016-10-08 16 views
0

のは、私はこのコードを持っているとしましょう:のstd :: STD上get_deleter :: STDを使用して初期化するshared_ptr ::バインド

class BaseObject 
{ 
public: 
    virtual void OnDestroy() {} 
}; 
template <typename T> 
struct myArrayDeleter 
{ 
    void operator()(T *p, std::size_t count) 
    { 
     for(std::size_t i = 0; i < count; i++) 
     { 
      static_cast<BaseObject*>((void*)(int(p) + sizeof(T) * i))->OnDestroy(); 
     } 
     delete [] p; 
    } 
}; 

そして、意図したとおりのは、それが動作することを想定してみましょう(それはせずに今書かれた、簡易版ですチェックしますが、基本的にはこのコードが何をすべきかを知っています)。
この部分では問題はありません。ただし、これをチェックしてください:

ただし、方法は機能していません。それはshared_ptrstd::bindに初期化したためです。 std::get_deleterは、テンプレートに間違ったタイプが指定されているため、常にnullptrを返します。どのタイプを渡すべきかわかりません。私はtypeid(U) == typeid(*m_shared.get())で行くことができる知っているが、これは私が欲しいものではありません

template <typename U> 
bool IsExactlyOfType() 
{ 
    if(!m_shared) 
     return false; 

    return ((void*)std::get_deleter<myDeleter<U>>(m_shared) != nullptr; 
} 

:私はmyDeleterは一引数でファンクタであり、それがこのようなコードで完璧に動作する非配列のコードでも試してみました。私ははるかに複雑なコードを持っており、その場合はこのメソッドだけが良いです。

もっと熟練したプログラマーは、指定するタイプをstd::get_deleterに教えてください。

+0

あなたのDeleterでは、ポインタが 'int'に収まらない場合はどうなりますか? 'sizeof(T *)> sizeof(int)'ならば?単純に '&p [i]'を使わないのはなぜですか? –

+0

まあ、私はコードでかなり複雑に書いていますが、基本的には意図どおりに動作しますが、ここではその点は重要ではありません。要点は、std :: get_deleterに指定する型がわからないということです。 – RazzorFlame

+0

私はあなたが実際のコードで 'int(p)'のようなキャストを使用していないことを期待しています。 ***はすべての64ビットシステムについて壊れます。 –

答えて

0

コンパイラがdecltypeを正しく翻訳していないことが判明しました。私はshared_ptrを初期化した直後にDeleterを取得しようとしました。しかし、関数内の同じdecltypeはわずかに他の型を生成していました。私は、デバッガでそれをチェックし、それがこの結果を生成:

コンストラクタで:

機能で
std::_Binder<std::_Unforced,grim::impl::TObjectArrayDeleter<APlayer>,std::_Ph<1> const &,unsigned int &> & 

std::_Binder<std::_Unforced,grim::impl::TObjectArrayDeleter<APlayer>,std::_Ph<1> const &,unsigned int const &> * 

は終わりを見てください - それは、追加のconstを追加しました。私は手動で変更する必要がありましたので、私のコードは次のようになります:

using D = std::_Binder<std::_Unforced,grim::impl::TObjectArrayDeleter<U>, 
         std::_Ph<1> const &,unsigned int &>; 

return ((void*)std::get_deleter<D>(m_shared)) != nullptr; 
関連する問題