添加来自unique_ptr< T>的隐式转换到T * [英] Add implicit conversion from unique_ptr<T> to T*

查看:185
本文介绍了添加来自unique_ptr< T>的隐式转换到T *的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

一般问题:如果不考虑这是否是一个好主意,我如何添加一个隐式转换操作符到已经定义的类?例如,假设我想要unique_ptr< T>隐式转换为T * ,但我不能只添加一个成员转换操作符,因为我不能改变unique_ptr类的定义。



选项:


  1. 有没有一些c ++ voodoo,成员函数?
    回答 - 远端:否。
    没有办法从代码中无法修改的类型添加隐式转换。<


  2. 我可以从std :: unique_ptr派生并添加自己的成员转换函数吗?这是否有任何严重的缺点?
    回答 - 远端:是(来自vsoftco)
    缺点尚未确定。到目前为止,继承了std :: unique_ptr,继承了它的构造函数,并声明了一个隐式的转换操作符,几乎没有任何代码需要被写入。


  3. <

    我只能在没有这个剩余生活的情况下生活吗?
    回答:我们会看到...
    如果我可以得到选项2 up和运行没有任何严重的副作用或负担,我会测试一段时间,并报告我是否认为这是值得的。


示例代码:

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

//错误C2664:'void(__vectorcall *)(MyClass *)'不能将参数1从'std :: unique_ptr< MyClass,std :: default_delete< _Ty& MyClass *'
std :: for_each(std :: begin(vec),std :: end(vec),[](MyClass * myClass)
{
myClass-> value + = 3;
});
}


解决方案

要使用 std :: unique_ptr<> :: get()函数,您可以:


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

      //自由函数
    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; // inherited base ctors
    operator T *()const {return this-> get();}
    };




  // wrapper用法:
unique_ptr_wrapper< int> upw {new int {42}};
int * p = upw; //隐式转换OK




  1. 1和2帮助你,所以你可以改善你的生活;)


General Question: Without going into whether or not it's a good idea, how can I add an implicit conversion operator to a class that has already been defined? For example, let's say that I want unique_ptr<T> to implicitly convert to T*, but I can't just add a member conversion operator because I can't change the definition of the unique_ptr class.

Options:

  1. Is there some c++ voodoo that I can use to make this happen without creating a member function?
    Answer-So-Far: NO.
    There is no way to add an implicit conversion away from a type that you can't modify in code.
    Just ... sadness.

  2. Could I derive from std::unique_ptr and add my own member conversion function? Are there any serious downsides to this?
    Answer-So-Far: Yes (from vsoftco)
    Downsides are yet to be determined. So far inheriting from std::unique_ptr, inheriting its constructors, and declaring an implicit conversion operator has worked splendidly with hardly any code needing to be written.

  3. Am I just going to have to live without this the rest of my life?
    Answer-So-Far: We'll see...
    If I can get option 2 up and running without any serious side-effect or burdens, I'll test it out for a while and report back on whether I think it's worth it. We'll see!

Example code:

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

解决方案

If you don't want to use std::unique_ptr<>::get() function, you can:

  1. Define a free function that takes a std::unique_ptr and returns the raw pointer returned by get, although I don't think it really makes your code better, like:

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

    Conversions of unique_ptr to raw pointers are OK, but they have to be explicit. Implicit conversion may lead to lots of headaches, since they may happen when you least expect them.

  2. It is a bad idea to derived from std::unique_ptr, as the latter is not made to be used as a base class (doesn't have a virtual destructor). In general, it is bad to derived from Standard Library classes. However, if you really insist, you can use a wrapper in which you define the implicit conversion operator, like:

    // 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();}
    };
    

and use is simply like

    // wrapper usage:
    unique_ptr_wrapper<int> upw{new int{42}};
    int* p = upw; // implicit conversion OK

  1. 1 and 2 can help you, so you may improve your life ;)

这篇关于添加来自unique_ptr&lt; T&gt;的隐式转换到T *的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆