C ++智能指针和指针到指针输出API。模板化"包装"

时间:2015-02-05 14:56:09

标签: c++ c++11 memory-management smart-pointers

在许多API中,尤其是类似C和COM的API,工厂函数将使用指针指针创建对象并将它们存储在调用者提供的位置。这与std :: unique_ptr,std :: shared_ptr以及其他遵循相同样式的其他内容不直接兼容(例如,对于COM或其他侵入式引用计数方案)。

void myApiFactory(int x, Foo **out);

std::unique_ptr<Foo> myFoo;
myApiFactory(33, &myFoo);//not possible

//works, but bit of a pain, especially with API's that have lots of such things
Foo *tmp = nullptr;
myApiFactory(33, &tmp);
myFoo.reset(tmp);

//What I'm looking for
myApiFactory(33, outPtr(myFoo));

我正在考虑的实现,似乎可以编译,但我不确定它是否正确和安全(例如,我理解(Foo**)(&myUniquePtr)不安全但编译并且适用于我)?

/**@brief Type created and returned by outPtr(T &smartPtr)*/
template<class T>
class OutPtr
{
public:
    typedef typename T::pointer pointer;
    /**Constructor for outPtr*/
    explicit OutPtr(T &smartPtr)
        : smartPtr(&smartPtr)
        , ptr(NULL)
    {}
    /**Move constructor for outPtr return*/
    OutPtr(OutPtr<T> &&mv)
        : smartPtr(mv.smartPtr)
        , ptr(mv.ptr)
    {
        mv.smartPtr = NULL;
        mv.ptr = NULL;
    }

    /**Destructor that stores the pointer set to the pointer to pointer in the
     * provided smart pointer.
     */
    ~OutPtr()
    {
        if (smartPtr)
            smartPtr->reset(ptr);
    }

    /**Implicit conversion to give the pointer to pointer to the function being
     * called.
     */
    operator pointer* ()
    {
        assert(ptr == NULL);
        return &ptr;
    }
private:
    T* smartPtr;
    pointer ptr;
    //Should not be used, cause a compile error
    OutPtr(const OutPtr&);
    OutPtr& operator = (const OutPtr&);
    OutPtr& operator = (OutPtr&&);
};


/**Provides a safe means to store an output pointer directly into an
 * std::unique_ptr or similar smart pointer. The only requirement
 * is that there is a pointer typedef, and a reset method that accepts a
 * pointer of that type.
 *
 * void someFunction(int a, int b, Foo **out);
 * 
 * std::unique_ptr<Foo,MyDeleter> foo;
 * someFunction(4, 23, outPtr(foo));
 */
template<class T>
OutPtr<T> outPtr(T &ptr)
{
    return OutPtr<T>(ptr);
}

1 个答案:

答案 0 :(得分:0)

这可行:

auto p = myFoo.get();
myApiFactory(33, &p);

因为myFoo中存储的地址作为l值存储在p中。