问题
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;
});
}
回答1:
If you don't want to use std::unique_ptr<>::get() function, you can:
Define a free function that takes a
std::unique_ptrand 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_ptrto 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 derive 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 ;)
来源:https://stackoverflow.com/questions/30553121/add-implicit-conversion-from-unique-ptrt-to-t