我们说我有这段代码:
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
并不起作用。这是因为我使用shared_ptr
初始化了std::bind
。 std::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
指定的类型吗?
答案 0 :(得分:0)
原来,编译器没有正确翻译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;