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

时间:2015-05-31 02:03:27

标签: c++ implicit-conversion unique-ptr

一般问题:如果不考虑是否是一个好主意,如何将隐式转换运算符添加到已定义的类中?例如,假设我想要unique_ptr&lt; T&gt;隐式转换为T * ,但我不能只添加成员转换运算符,因为我无法更改unique_ptr类的定义。

选项:

  1. 我是否可以使用一些c ++巫毒来实现这一目标而不创建成员函数?
    答案 - 远:否。
    无法在代码中无法修改的类型中添加隐式转换。
    只是......悲伤。

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

  3. 我将不得不在余生中度过余生吗?
    答案 - 远:我们会看到......
    如果我可以选择2运行而没有任何严重的副作用或负担,我会测试一段时间并报告我是否认为值得。我们会看到!

  4. 示例代码:

    #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;
        });
    }
    

1 个答案:

答案 0 :(得分:5)

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

  1. 定义一个自由函数,它接受std::unique_ptr并返回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派生是一个坏主意,因为后者不能用作基类(没有虚拟析构函数)。通常,从标准库类派生是不好的。但是,如果您真的坚持,可以使用包装器来定义隐式转换运算符,例如:

    // 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();}
    };
    
  3. 并且使用就像

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