对标题感到抱歉,我找不到更好的标题。
假设我有一个带有特殊删除语义的类,它需要调用一个函数而不是被delete
删除,我们称之为releaseable_object
:
struct releaseable_object
{
releaseable_object() : dummy_ptr(new int) {}
void Release()
{
std::cout << "Releasing releaseable object\n";
delete dummy_ptr;
}
int *const dummy_ptr;
};
这个releaseable_object
是一堆其他对象的基类,每个对象都由一个只返回指针的工厂构建。
我正在尝试使用调用std::unique_ptr
函数的自定义删除器将每个类包装到releaseable_object::Release()
中,因此我创建了一个辅助结构来处理一些通用的东西:
// std::is_base_of<releaseable_object, T>::value must be true
template <typename T> struct Managed
{
using type = T;
static void deleter(type *object)
{
std::cout << "Release!\n";
object->Release();
};
using pointer = std::unique_ptr<T, decltype(deleter)>;
};
然后,一堆派生类执行所有特定的初始化并调用te factory:
struct ManagedA : Managed<A>
{
using base = Managed<A>;
using base::pointer;
using base::deleter;
ManagedA(/* lots of parameters */) :
m_pointer(nullptr, deleter)
{
// do A specific stuff...
A *a = factory::CreateA(/* lots of parameters */);
// more A specific stuff...
// wrap the pointer:
m_pointer.reset(a);
}
pointer m_pointer;
};
如果我尝试编译上面的代码,它会抱怨unique_ptr
(demo here),我不知道我在那里做错了什么,错误是关于a的实例化元组(完整的错误日志在ideone演示中):
tuple: In instantiation of ‘struct std::_Head_base<1u, void(A*), false>’:
tuple:229:12: recursively required from ‘struct std::_Tuple_impl<1u, void(A*)>’
tuple:229:12: required from ‘struct std::_Tuple_impl<0u, A*, void(A*)>’
tuple:521:11: required from ‘class std::tuple<A*, void(A*)>’
bits/unique_ptr.h:127:57: required from ‘class std::unique_ptr<A, void(A*)>’
如果我删除m_pointer
成员,则编译成功。我很遗憾,我会很感激有关如何解决编译错误的任何提示。
感谢您的关注。
答案 0 :(得分:3)
问题是decltype(deleter)
是函数类型而不是指向函数的类型。将pointer
声明更改为
using pointer = std::unique_ptr<T, decltype(deleter)*>; // or spell out void(*)(T*)
会解决它。
请注意,函数对象类型通常优于唯一指针删除器的函数指针类型,因为函数指针必须存储在对象本身中。即,
sizeof(std::unique_ptr<foo*,void(*)(foo*)>) == sizeof(foo*) + sizeof(void(*)(foo*))
但是如果使用空删除器类型,大多数实现都将利用空基优化:
struct deleter_type {
void operator () (foo*) {
// ...
}
};
sizeof(std::unique_ptr<foo*,deleter_type>) == sizeof(foo*)
Here's how your sample code would be written using a deleter type.