On Monday 17 October 2016 10:14:52
mihailn...@gmail.com wrote:
> Hello,
>
> In many cases there is the need to track an object and use it only if it is
> still alive. This can't be achieved with raw pointers.
>
> The only way, right now, is by using a shared_ptr + weak_ptr.
> But this has the downside of making your object sharable, where one does
> not intent to (granted with use_count of 1 most of the time).
The fundamental problem with what you're intending to do is this: unique_ptr
is a *unique* ptr. There are no other owners. Suppose there was some
weak_unique_ptr for unique_ptr the way we have weak_ptr for shared_ptr.
What does weak_unique_ptr::lock() return? It cannot return unique_ptr, since
then you might end up with two unique_ptrs owning the same object. You could
say that the unique_ptr returned from lock() has an empty deleter, or that
weak_unique_ptr can be directly dereferenced. but then you lose atomicity
between checking weak_unique_ptr for having been nulled out and deref'ing it
to access the object. Now, that may or may not be a problem, but it's a
problem that would have to be addressed for a "production-ready"
implementation.
That said, you could do the following:
Construct the object with make_shared, create a custom deleter for unqiue_ptr
and move the shared_ptr holding the object into the deleter of a unique_ptr
pointing to the object. You can type-erase the deleter by holding a
shared_ptr<void>.
struct ObservableUniquePtrDeleter {
std::shared_ptr<void> ptr;
void operator(void *) { ptr.reset(); }
};
template <typename T>
using ObservableUniquePtr = std::unique_ptr<T, ObservableUniquePtrDeleter>;
template <typename T, typename ...Args>
auto make_observable_unique(Args &&...args) {
auto p = std::make_shared<T>(std::forward<Args>(args)...);
auto t = p.get();
return ObservableUnqiuePtr<T>{t, std::move(p)};
}
template <typename T>
auto get_weak_ref(const ObservableUniquePtr<T> &ptr) {
std::weak_ptr<T> weak;
if (ptr)
weak = static_pointer_cast<T>(ptr.get_deleter().ptr);
return weak;
}
(completely untested)
>
> I think there is a middle ground - b/w
>
> A) Object has explicit single-owner lifetime (unique_ptr), BUT pointers
> are potentially dangling and object can be destroyed at any time.
> B) Pointers which never dangle and object is kept alive while using it, BUT
> the life time is no longer explicit - anyone can keep the object alive OR
> in, the case of shared_ptr<unique_ptr>, must have special shared_ptr
> instance which is "delegated" (commented) to be the owner.
>
>
> The middle ground is:
> A') Object has explicit single-owned lifetime with pointers which never
> dangle, BUT object might be destroyed at any time.
>
>
> This middle ground is implementable in current C++, but is not very pretty,
> manly because there are no extension pointes to unique_ptr - one need to
> use it as member and reimplement its interface.
>
>
> My question is - has anyone implemented such a pointer ("production level")
> OR you guys just use the shared_ptr in these scenarios?
--
Marc Mutz <
marc...@kdab.com> | Senior Software Engineer
KDAB (Deutschland) GmbH & Co.KG, a KDAB Group Company
Tel:
+49-30-521325470
KDAB - The Qt, C++ and OpenGL Experts