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

C++ Smart Pointers and pointer-to-pointer output API's. Templated "wrapper"

本文关键字:指针 wrapper API 智能 输出 C++      更新时间:2023-10-16

在许多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);
}

这可以工作:

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

因为存储在CCD_ 2中的地址被存储在CCD_。