添加从 unique_ptr<T> 到 T* 的隐式转换

Add implicit conversion from unique_ptr<T> to T*

一般问题: 不考虑这是否是个好主意,我如何向已经定义的 class 添加隐式转换运算符?例如,假设 我希望 unique_ptr 隐式转换为 T*,但我不能只添加成员转换运算符,因为我无法更改unique_ptrclass.

的定义

选项:

  1. 是否有一些 c++ 巫术可以让我在不创建成员函数的情况下实现这一点?
    到目前为止的答案:没有。
    无法从无法在代码中修改的类型中添加隐式转换。
    只是...悲伤。

  2. 我可以从std::unique_ptr派生并添加我自己的成员转换函数吗?这有什么严重的缺点吗?
    到目前为止的答案:是的(来自 vsoftco)
    缺点尚未确定.到目前为止,从 std::unique_ptr 继承,继承它的构造函数,并声明一个隐式转换运算符,效果非常好,几乎不需要编写任何代码。

  3. 我的余生都将不得不在没有这个的情况下生活吗?
    到目前为止的答案:我们会看到...
    如果我可以得到选项 2 和 运行 而没有任何严重的副作用或负担,我会测试一段时间并报告是否我认为这是值得的。我们拭目以待!

示例代码:

#include <algorithm>
#include <memory>
#include <vector>

struct MyClass
{
    MyClass(int v) : value(v) {}

    int value;
};

int main()
{
    auto vec = std::vector<std::unique_ptr<MyClass>>();

    vec.push_back(std::make_unique<MyClass>(1));
    vec.push_back(std::make_unique<MyClass>(2));

    // error C2664: 'void (__vectorcall *)(MyClass *)' : cannot convert argument 1 from 'std::unique_ptr<MyClass,std::default_delete<_Ty>>' to 'MyClass *'
    std::for_each(std::begin(vec), std::end(vec), [](MyClass* myClass)
    {
        myClass->value += 3;
    });
}

如果不想使用std::unique_ptr<>::get()功能,可以:

  1. 定义一个自由函数,它接受 std::unique_ptr 和 returns 由 get 返回的原始指针,虽然我不认为它真的使你的代码更好,例如:

    // free function
    template<typename T>
    T* get_raw_ptr(const std::unique_ptr<T>& up)
    {
        return up.get();
    }
    

    unique_ptr 到原始指针的转换是可以的,但它们必须是显式的。隐式转换可能会导致很多麻烦,因为它们可能会在您最意想不到的时候发生。

  2. 派生自 std::unique_ptr 是个坏主意,因为后者不能用作基础 class(没有虚拟析构函数) .一般来说,从标准库 classes 派生是不好的。但是,如果你真的坚持,你可以使用一个包装器,在其中定义隐式转换运算符,例如:

    // wrapper
    template <class T, class Deleter = std::default_delete<T>> 
    class unique_ptr_wrapper: public std::unique_ptr<T, Deleter>
    {
    public:
        using std::unique_ptr<T, Deleter>::unique_ptr; // inheriting base ctors
        operator T* () const {return this->get();}
    };
    

使用起来就像

    // wrapper usage:
    unique_ptr_wrapper<int> upw{new int{42}};
    int* p = upw; // implicit conversion OK
  1. 1 和 2 可以帮助你,所以你可能会改善你的生活 ;)