为 C++03 编译器编写部分 unique_ptr,它使用较新的编译器在通用代码库上运行

Writing partial unique_ptr for C++03 compiler which operates on common codebase with newer compilers

我需要为 C++03 编写 unique_ptr 的实现,它只会吸收在启用 C++11 的其他平台下对公共代码库所做的更改。也就是说,它不需要检查任何东西,一切都会被其他平台的编译器检查。但它需要正确传递和销毁对象。

这是测试代码示例。还有 full test online.

template <class T> std2::unique_ptr<T> pass_through(std2::unique_ptr<T> p) { return p; }
...
std2::unique_ptr<A> a1 = std2::make_unique<B>();
std2::unique_ptr<A> a2 = std2::move(pass_through(a1));                             // doesn't work
std2::unique_ptr<A> a2 = (const std2::unique_ptr<A>&)std2::move(pass_through(a1)); // doesn't work
std2::unique_ptr<A> a2 = (const std2::unique_ptr<B>&)std2::move(pass_through(a1)); // works
std2::unique_ptr<B> a2 = std2::move(pass_through(a1));                             // works

unique_ptr 实施:

class Num { protected: static int i; }; int Num::i = 0;

template<class Data>
class unique_ptr : Num
{
    int _i = i++;
    mutable Data *_data;

public:
    explicit unique_ptr(Data* data = nullptr) 
    { _data = data; std::cout << _i << ": cons" << std::endl; }

    template<class T>
    unique_ptr(unique_ptr<T>& other) :
        _data((Data*)other.release())
    { std::cout << _i << ": copy cons <T>" << std::endl; }

    template<class T>
    unique_ptr(const unique_ptr<T>& other) :
        _data((Data*)other.release())
    { std::cout << _i << ": copy cons const <T>" << std::endl; }

    ~unique_ptr() { std::cout << _i << ": deleting :" << _data << std::endl; delete _data; _data = 0; }

    unique_ptr& operator=(Data* data)
    { reset(data); return *this; }

    template<class T>
    unique_ptr& operator=(unique_ptr<T>& other) {
        std::cout << "assign <T>" << std::endl;
        reset((Data*)other.release());
        return *this;
    }

    template<class T>
    unique_ptr& operator=(const unique_ptr<T>& other) {
        std::cout << "assign const <T>" << std::endl;
        reset((Data*)other.release());
        return *this;
    }

    operator bool() const { return _data != nullptr; }

    Data* release() const
    { Data* res = _data; _data = nullptr; return res; }

    template <class T>
    void reset(T* data)
    { Data* old = _data; _data = (Data*)data; delete old; }
};

template <class T>       std2::unique_ptr<T>& move(      std2::unique_ptr<T>& data) { return data; }
template <class T> const std2::unique_ptr<T>& move(const std2::unique_ptr<T>& data) { return data; }

template<class Data>
inline unique_ptr<Data> make_unique() { return unique_ptr<Data>(new Data()); }

类:

struct A {
    A() { std::cout << "A()" << std::endl; }
    virtual ~A() { std::cout << "~A()" << std::endl; };
};

struct B : public A {
    B() : A() { std::cout << "B()" << std::endl; }
    ~B() { std::cout << "~B" << std::endl; };
};

第一个选项的输出。看起来已经完成了一些额外的复制(memcpy)。

A()
B()
0: cons
1: copy cons const <T>
0: deleting :0000000000000000
2: copy cons <T>
Inside pass_through
3: copy cons <T>
2: deleting :0000000000000000
3: deleting :000001CC492B1790   // This one is #3
~B
~A()
3: deleting :000001CC492B1790   // This one is also #3

你能帮我解决这个双重删除问题吗?

模板永远不是复制构造函数。

unique_ptr(const unique_ptr<Data>& other)
unique_ptr(unique_ptr<Data>& other)

写这两个。

operator=也类似。