2014-02-11 70 views
1

对不起,关于标题,我不能有一个更好的。在基类上声明的std :: unique_ptr

假设我有特殊删除语义,这需要调用一个函数,而不是通过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)>; 
}; 

然后,派生类的一堆其中完成所有的具体初始化,并呼吁德工厂:

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_ptrdemo here),我不“知道我做错了什么存在的错误是关于一个元组的实例化(完整的错误日志是在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

是不是更容易重载'删除'? OMG! –

回答

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.

+0

OMG!我的失败!非常感谢。 –

+0

@PaperBirdMaster我加了一些关于为什么使用删除类型通常比删除函数更受欢迎的信息。 – Casey

+0

非常有用!但我已经为你+1了,我无法为你的分数添加更多分数! ;) –

相关问题