从unique_ptr <t,deleter>中提取unique_ptr

时间:2017-04-30 16:34:32

标签: c++ c++11

有人可以建议如何使用自定义deletor从templatised唯一指针池返回唯一指针。

在下面的代码片段中,我使用ObjectPool.h作为我的模板类来获取一堆独特的指针。 我正在使用ObjectPool在DBConnection.h中创建一个sharedpool对象,稍后在DBConnection.cpp中我只是将对象返回到DBExec。

我在DBConnection.cpp中遇到与将删除指针转换为普通唯一指针相关的编译错误。

> Class that will manage connection objects. 
**DBConnectionPool.h**
#ifndef DBCONNECTIONPOOL_H
#define DBCONNECTIONPOOL_H
#include "DBExec.h"
#include "ObjectPool.h"
class DBConnectionPool {
    static SharedPool<DBExec> pool;
    static DBConnectionPool* instance;
    DBConnectionPool& operator=(const DBConnectionPool&);
    DBConnectionPool(const DBConnectionPool&);;
    DBConnectionPool(){};
public:
    ...
    **static std::unique_ptr<DBExec> getQueryObject();**
};



#endif /* DBCONNECTIONPOOL_H */

**DBConnection.cpp**
>implementation of getQueryObject 
 **std::unique_ptr<DBExec>  DBConnectionPool::getQueryObject() {
    return std::move(pool.acquire());
}**

/* Class that manages the unique pointer */ 
**ObjectPool.h**
#ifndef OBJECTPOOL_H
#define OBJECTPOOL_H
#include <memory>
#include <stack>
#include <mutex>
#include <assert.h>
template <class T>
class SharedPool {

/* Class that manages the unique pointer */ 
public:
    using ptr_type = std::unique_ptr<T, std::function<void(T*)> >;

    SharedPool() {
    }

    virtual ~SharedPool() {
    }

    void add(std::unique_ptr<T> t) {
        std::lock_guard<std::mutex>  lck (mt);
        pool_.push(std::move(t));
    }

    ptr_type acquire() {
        std::lock_guard<std::mutex>  lck (mt);
        assert(!pool_.empty());
        ptr_type tmp(pool_.top().release(),
                [this](T * ptr) {
                    this->add(std::unique_ptr<T>(ptr));
                });
        pool_.pop();
        return std::move(tmp);
    }

    bool empty() const {
        std::lock_guard<std::mutex>  lck (mt);
        return pool_.empty();
    }

    size_t size() const {
        std::lock_guard<std::mutex>  lck (mt);
        return pool_.size();
    }
    std::stack<std::unique_ptr<T>>& getPoolStack () {
        return pool_;
    }
private:
> thread safe 
    std::mutex mt;
    std::stack<std::unique_ptr<T> > pool_;
};

#endif /* OBJECTPOOL_H */

3 个答案:

答案 0 :(得分:1)

std::unique_ptr<T,D>std::unique_ptr<T>是不相关的类型(除非D=std::default_delete<T>)。因此,您需要在所有typedef中指定删除器的类型。

接下来的问题是你无法实际输入删除器的类型,因为它是lambda类型。因此,您可能必须从lambda切换到命名的可调用类型。

template <class T>
class SharedPool {
public:
    class Deleter {
    public:
        void operator()(T* ptr) const {
            pool->add(std::unique_ptr<T,Deleter>(ptr));
        }
    private:
        explicit Deleter(SharedPool* pool) : pool(pool) {}
        SharedPool* pool;
        friend class SharedPool<T>;
    };
    using ptr_type = std::unique_ptr<T, Deleter>;

您也可以考虑使用std::shared_ptr,因为它会删除其删除类型,但您似乎不需要共享。

答案 1 :(得分:1)

如果我理解正确,您希望从具有自定义删除功能的常规unique_ptr获取。这是不可能的,因为从另一个unique_ptr返回unique_ptr会违反该指针的唯一性。你唯一的选择是将它转换成某种东西,删除器是从类型中隐藏的(即类型擦除)。

答案 2 :(得分:0)

听起来你想要的是类型擦除,或​​至少部分类型擦除。一个简单的解决方案就是使用std::shared_ptr

std::shared_ptr<T>(new T, custom_deleter);

这将提供超过std::unique_ptr的一些开销,但有些开销是不可避免的。