添加从 unique_ptr<T> 到 T* 的隐式转换
Add implicit conversion from unique_ptr<T> to T*
一般问题: 不考虑这是否是个好主意,我如何向已经定义的 class 添加隐式转换运算符?例如,假设 我希望 unique_ptr 隐式转换为 T* ,但我不能只添加成员转换运算符,因为我无法更改unique_ptrclass.
的定义
选项:
是否有一些 c++ 巫术可以让我在不创建成员函数的情况下实现这一点?
到目前为止的答案:没有。
无法从无法在代码中修改的类型中添加隐式转换。
只是...悲伤。
我可以从std::unique_ptr派生并添加我自己的成员转换函数吗?这有什么严重的缺点吗?
到目前为止的答案:是的(来自 vsoftco)
缺点尚未确定.到目前为止,从 std::unique_ptr 继承,继承它的构造函数,并声明一个隐式转换运算符,效果非常好,几乎不需要编写任何代码。
我的余生都将不得不在没有这个的情况下生活吗?
到目前为止的答案:我们会看到...
如果我可以得到选项 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()
功能,可以:
定义一个自由函数,它接受 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
到原始指针的转换是可以的,但它们必须是显式的。隐式转换可能会导致很多麻烦,因为它们可能会在您最意想不到的时候发生。
派生自 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 和 2 可以帮助你,所以你可能会改善你的生活 ;)
一般问题: 不考虑这是否是个好主意,我如何向已经定义的 class 添加隐式转换运算符?例如,假设 我希望 unique_ptr
选项:
是否有一些 c++ 巫术可以让我在不创建成员函数的情况下实现这一点?
到目前为止的答案:没有。
无法从无法在代码中修改的类型中添加隐式转换。
只是...悲伤。我可以从std::unique_ptr派生并添加我自己的成员转换函数吗?这有什么严重的缺点吗?
到目前为止的答案:是的(来自 vsoftco)
缺点尚未确定.到目前为止,从 std::unique_ptr 继承,继承它的构造函数,并声明一个隐式转换运算符,效果非常好,几乎不需要编写任何代码。我的余生都将不得不在没有这个的情况下生活吗?
到目前为止的答案:我们会看到...
如果我可以得到选项 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()
功能,可以:
定义一个自由函数,它接受
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
到原始指针的转换是可以的,但它们必须是显式的。隐式转换可能会导致很多麻烦,因为它们可能会在您最意想不到的时候发生。派生自
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 和 2 可以帮助你,所以你可能会改善你的生活 ;)