c++11 - 在基类上声明的 std::unique_ptr

标签 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)>;
};

然后,一堆派生类完成所有特定的初始化并调用工厂:

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 ),我不知道我在那里做错了什么,错误与实例化有关一个元组(完整的错误日志在 ideone demo 中):

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 成员,那么编译就会成功。我对此感到非常困惑,如果有任何有关如何修复编译错误的提示,我将不胜感激。

感谢您的关注。

最佳答案

问题是 decltype(deleter) 是函数类型而不是函数指针类型。将指针声明更改为

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

关于c++11 - 在基类上声明的 std::unique_ptr,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21707279/

相关文章:

c++ - 带有标准容器的 unique_ptr : attempting to reference a deleted function

c++ - 如何使用 STL 正确跟踪地址?

c++ - 为什么成员 `float x` 在 main() 中为对象 `0.` 和 `a` 初始化为 `b`?

c++ - 使用 `std::vector` 时 `std::unique_ptr` 中的数据不同

c++ - 为右值特化 std::swap

c++ - 为什么 lambda 没有从到达范围捕获类型 const double,而 const int 是?

c++ - 继承类中的 shared_from_this() 类型错误(是否有 dyn.type-aware 共享指针?)

C++ 为什么 `observer_ptr<W>` 有一个采用 `W*` 的构造函数?

c++ - 重新分配std::unique_ptr时是否释放内存?

c++ - 在 shared_ptr 过期后定位 weak_ptr