用Std::bind初始化Std::shared_ptr的Std::get_deleter

std::get_deleter on std::shared_ptr initialized with std::bind

本文关键字:Std deleter ptr get shared bind 初始化      更新时间:2023-10-16

假设我有这样的代码:

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;
    }
};

让我们假设它按预期工作(这是一个简化版本,现在没有检查,但基本上你知道这段代码应该做什么)。
这部分我没有问题。但是,看看这个:

class AActor
    : public BaseObject
{
public:
    virtual void OnDestroy() override
    {
        // some code here
    }
};
template <typename T>
class SimplifiedHolder
{
protected:
    std::shared_ptr<T> m_shared;
    std::size_t m_size;
public:
    // Some not important code here
    // WE ASSUME HERE THAT IT ALWAYS HOLDS ARRAY
    // sizeOfArray always > 1
    template <typename U>
    SimplifiedHolder(U *ptr, std::size_t sizeOfArray)
        : m_size(sizeOfArray)
    {
        m_shared = std::shared_ptr<T>(ptr,
                           std::bind(&myArrayDeleter<U>(), std::placeholders::_1, m_size));
    }
    // And now as we initialize our shared_ptr with template
    // we can check if it is exactly of type "U"
    template <typename U>
    bool IsExactlyOfType()
    {
        if(!m_shared)
            return false;
        return ((void*)std::get_deleter<myArrayDeleter<U>>(m_shared)) != nullptr;
    }
};

然而,方法IsExactlyOfType不起作用。这是因为我用std::bind初始化了shared_ptrstd::get_deleter总是返回nullptr,因为模板中指定了错误的类型。我不知道该传递哪种类型。我还尝试了非数组代码,其中myDeleter是一个只有一个参数的函子,它与这样的代码完美地工作:

template <typename U>
bool IsExactlyOfType()
{
     if(!m_shared)
         return false;
     return ((void*)std::get_deleter<myDeleter<U>>(m_shared) != nullptr;
}

我知道我可以用typeid(U) == typeid(*m_shared.get()),但这不是我想要的。我有更复杂的代码,在这种情况下,只有这个方法是好的。

有经验的程序员能告诉我该给std::get_deleter指定什么类型吗

原来编译器没有正确翻译decltype。我试图在初始化shared_ptr后立即删除它,它工作了。然而,同样的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;