【问题标题】:How to set object that is acquired from RAII style smart object pool in C++?如何在 C++ 中设置从 RAII 样式智能对象池获取的对象?
【发布时间】:2020-04-21 09:53:51
【问题描述】:

我使用 RAII 风格的智能对象池,我想将获取的对象设置为另一个类的成员。

T.C. 建议的智能对象池。 :

template <class T, class D = std::default_delete<T>>
class SmartObjectPool 
{
    private:
        struct ReturnToPool_Deleter {
            explicit ReturnToPool_Deleter(std::weak_ptr<SmartObjectPool<T, D>* > pool) : pool_(pool) {

            }

            void operator()(T* ptr) {
                if (auto pool_ptr = pool_.lock())
                    (*pool_ptr.get())->add(std::unique_ptr<T, D>{ptr});
                else
                    D{}(ptr);
            }
            private:
                std::weak_ptr<SmartObjectPool<T, D>* > pool_;
        };

    public:
        using ptr_type = std::unique_ptr<T, ReturnToPool_Deleter >;

        SmartObjectPool() : this_ptr_(new SmartObjectPool<T, D>*(this)) {}
        virtual ~SmartObjectPool(){}

        void add(std::unique_ptr<T, D> t) {
            pool_.push(std::move(t));
        }

        ptr_type acquire() {
            if (pool_.empty())
                throw std::out_of_range("Cannot acquire object from an empty pool.");

            ptr_type tmp(pool_.top().release(),
                            ReturnToPool_Deleter{
                            std::weak_ptr<SmartObjectPool<T, D>*>{this_ptr_}});
            pool_.pop();
            return std::move(tmp);
        }

        bool empty() const {
            return pool_.empty();
        }

        size_t size() const {
            return pool_.size();
        }

    private:
        std::shared_ptr<SmartObjectPool<T, D>* > this_ptr_;
        std::stack<std::unique_ptr<T, D> > pool_;
};

我想将获取的对象设置为另一个类(Setter)的成员的Setter类:

class Setter {
    public:
        void setValue(SmartObjectPool<int>::ptr_type value) {
            m_value = std::move(value);
        }
    private:
        SmartObjectPool<int>::ptr_type m_value;
};

和主要实现:

int main()
{

SmartObjectPool<int> pool;
pool.add(std::make_unique<int>());
assert(pool.size() == 1u);
{
  auto obj = pool.acquire();
  Setter setter;
  setter.setValue(std::move(obj));
  assert(pool.size() == 0u);
}
assert(pool.size() == 1u);
auto obj = pool.acquire();

return 0;

}

我收到有关 ReturnToPool_Deleter 构造函数的编译错误:

In file included from /usr/include/c++/5/functional:55:0,
                 from /usr/include/c++/5/memory:79,
                 from src/main.cpp:1:
/usr/include/c++/5/tuple: In instantiation of ‘constexpr std::_Head_base<_Idx, _Head, false>::_Head_base() [with long unsigned int _Idx = 1ul; _Head = SmartObjectPool<int>::ReturnToPool_Deleter]’:
/usr/include/c++/5/tuple:353:15:   required from ‘constexpr std::_Tuple_impl<_Idx, _Head>::_Tuple_impl() [with long unsigned int _Idx = 1ul; _Head = SmartObjectPool<int>::ReturnToPool_Deleter]’
/usr/include/c++/5/tuple:202:29:   required from ‘constexpr std::_Tuple_impl<_Idx, _Head, _Tail ...>::_Tuple_impl() [with long unsigned int _Idx = 0ul; _Head = int*; _Tail = {SmartObjectPool<int>::ReturnToPool_Deleter}]’
/usr/include/c++/5/tuple:602:20:   required from ‘constexpr std::tuple<_T1, _T2>::tuple() [with _T1 = int*; _T2 = SmartObjectPool<int>::ReturnToPool_Deleter]’
/usr/include/c++/5/bits/unique_ptr.h:158:14:   required from ‘constexpr std::unique_ptr<_Tp, _Dp>::unique_ptr() [with _Tp = int; _Dp = SmartObjectPool<int>::ReturnToPool_Deleter]’
src/main.cpp:59:7:   required from here
/usr/include/c++/5/tuple:105:22: error: no matching function for call to ‘SmartObjectPool<int>::ReturnToPool_Deleter::ReturnToPool_Deleter()’
       : _M_head_impl() { }
                      ^
src/main.cpp:11:22: note: candidate: SmartObjectPool<T, D>::ReturnToPool_Deleter::ReturnToPool_Deleter(std::weak_ptr<SmartObjectPool<T, D>*>) [with T = int; D = std::default_delete<int>]
             explicit ReturnToPool_Deleter(std::weak_ptr<SmartObjectPool<T, D>* > pool)
                      ^
src/main.cpp:11:22: note:   candidate expects 1 argument, 0 provided
src/main.cpp:10:16: note: candidate: SmartObjectPool<int>::ReturnToPool_Deleter::ReturnToPool_Deleter(const SmartObjectPool<int>::ReturnToPool_Deleter&)
         struct ReturnToPool_Deleter {
                ^
src/main.cpp:10:16: note:   candidate expects 1 argument, 0 provided
src/main.cpp:10:16: note: candidate: SmartObjectPool<int>::ReturnToPool_Deleter::ReturnToPool_Deleter(SmartObjectPool<int>::ReturnToPool_Deleter&&)
src/main.cpp:10:16: note:   candidate expects 1 argument, 0 provided
src/main.cpp: In function ‘int main()’:
src/main.cpp:87:10: note: synthesized method ‘constexpr Setter::Setter()’ first required here
   Setter setter;
          ^
Makefile:17: recipe for target 'obj/main.o' failed
make: *** [obj/main.o] Error 1

问题:如何将获取的对象设置为另一个类的成员?

【问题讨论】:

  • 这是整个错误信息吗?没有更多的线路了吗?编译器是否没有给出错误发生的确切行?
  • 我编辑了帖子并添加了所有错误行。它表示 Setter 类。

标签: c++ raii


【解决方案1】:

问题出在下面一行

Setter setter;

此行尝试默认构造 Setter,但 Setter 不可默认构造。 Setter 的默认构造函数被隐式删除,因为它有一个 SmartObjectPool&lt;int&gt;::ptr_type 成员,它本身不是默认可构造的。

SmartObjectPool&lt;int&gt;::ptr_typestd::unique_ptr&lt;T, ReturnToPool_Deleter &gt; 的别名。现在让我们看看cppreferencestd::unique_ptr&lt;T, Deleter&gt; 的默认构造函数有什么看法。

1) 构造一个不拥有任何东西的 std::unique_ptr。值初始化存储的指针和存储的删除器。要求 Deleter 是 DefaultConstructible 并且构造不会引发异常。

如您所见,如果Deleter 是默认可构造的,则只能默认构造unique_ptr,在您的情况下,这不是真的:ReturnToPool_Deleter 不是默认构造的。

你可以做这样的事情,而不是你现在正在做的事情:

using Deleter = std::function<void(T* ptr)>;
using ptr_type = std::unique_ptr<T, Deleter>;

然后

auto deleter = [pool_ = std::weak_ptr<SmartObjectPool<T, D>*>{this_ptr_} ](T* ptr) {
    if (auto pool_ptr = pool_.lock()) {
        (*pool_ptr.get())->add(std::unique_ptr<T, D>{ptr});
    } else {
        D{}(ptr);
    }
};

ptr_type tmp(pool_.top().release(), deleter);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-04-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-29
    相关资源
    最近更新 更多