在基类上声明的std :: unique_ptr

时间:2014-02-11 16:20:54

标签: c++11 smart-pointers

对标题感到抱歉,我找不到更好的标题。

假设我有一个带有特殊删除语义的类,它需要调用一个函数而不是被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_ptrdemo 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成员,则编译成功。我很遗憾,我会很感激有关如何解决编译错误的任何提示。

感谢您的关注。

1 个答案:

答案 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.