添加来自unique_ptr< T>的隐式转换到T * [英] Add implicit conversion from unique_ptr<T> to T*
问题描述
一般问题:如果不考虑这是否是一个好主意,我如何添加一个隐式转换操作符到已经定义的类?例如,假设我想要unique_ptr< T>隐式转换为T * ,但我不能只添加一个成员转换操作符,因为我不能改变unique_ptr类的定义。
选项:
-
有没有一些c ++ voodoo,成员函数?
回答 - 远端:否。
没有办法从代码中无法修改的类型添加隐式转换。< -
我可以从std :: unique_ptr派生并添加自己的成员转换函数吗?这是否有任何严重的缺点?
回答 - 远端:是(来自vsoftco)
缺点尚未确定。到目前为止,继承了std :: unique_ptr,继承了它的构造函数,并声明了一个隐式的转换操作符,几乎没有任何代码需要被写入。
<
我只能在没有这个剩余生活的情况下生活吗?
回答:我们会看到...
如果我可以得到选项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()
函数,您可以:
-
定义一个自由函数,它接受
std :: unique_ptr
,并返回get
,虽然我不认为它真的使你的代码更好,如://自由函数
template< typename T>
T * get_raw_ptr(const std :: unique_ptr< T>& up)
{
return up.get();
}
转换
unique_ptr
到原始指针都行,但它们必须是显式的。隐式转换可能会导致很多头痛,因为它们可能在您最不希望发生时发生。 -
从
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和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:
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.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.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:
Define a free function that takes a
std::unique_ptr
and returns the raw pointer returned byget
, 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.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 and 2 can help you, so you may improve your life ;)
这篇关于添加来自unique_ptr< T>的隐式转换到T *的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!