2

So I have some code:

class Thing
{
public:
    Thing() = default;
};

class DbOfThings
{
public:
    DbOfThings() = default;

    std::weak_ptr<Thing> GetEntry(int someKey) const
    {
        // returns a weak_ptr from mThings, or null if a Thing
        // that has someKey was not found
        return std::weak_ptr<Thing>(nullptr);
    }
private
    // Idea is that this object owns these things, but other objects can grab a thing from here - but the thing can be killed off at any time
    std::vector<std::share_ptr<Thing>> mThings;

But this fails to compile with:

no known conversion for argument 1 from 'std::nullptr_t' to 'const std::weak_ptr&'

Why? Is my approch for letting other objects hold onto something that is owned by another wrong? This seems like a valid use case for weak_ptr to me. How can I make this work?

paulm
  • 5,629
  • 7
  • 47
  • 70
  • It seems there is no such constructor, but you can just use default: `return {};` – zch Mar 28 '14 at 18:40
  • Why use `shared_ptr` rather than `unique_ptr` if the vector is the only thing owning the objects? (Or can you not create `weak_ptr`s for objects owned by `unique_ptr`, even though weak pointers will not not cause a change in ownership for the object pointed to?) – JAB Mar 28 '14 at 18:46
  • ...Oh, I see. Because `shared_ptr` can take a `weak_ptr` as constructor, allowing weak pointers to objects owned by a unique pointer would require killing the unique pointer, and though `shared_ptr` has a `unique_ptr` constructor that does just that doing so indirectly would probably have weird effects. – JAB Mar 28 '14 at 18:59
  • @jab more fundamentally, `.lock()` is how you access a `weak_ptr`, and if it cannot extend the lifetime of the pointed to object, what good is it? – Yakk - Adam Nevraumont Mar 28 '14 at 23:09
  • yeah its strange that there isn't a weak_ptr for unique_ptr - when you want to pass it around but not change owner – paulm Mar 28 '14 at 23:31
  • @paulm -- in Rust you can have a "borrowed" pointer which is pretty much what you want. The (unsafe) C++ equivalent is to temporarily use an old-style pointer using `.get()`. You could probably implement unique+weak semantics in C++, but that would raise the overhead. – Adrian Ratnapala May 11 '16 at 09:46

1 Answers1

9

weak_ptr doesn't have any constructors that take a nullptr_t or raw pointers, so you cannot construct one with nullptr as an argument. To obtain an empty weak_ptr just default construct one.

std::weak_ptr<Thing> GetEntry(int someKey) const
{
    // returns a weak_ptr from mThings, or null if a Thing
    // that has someKey was not found
    return std::weak_ptr<Thing>();
    // or
    // return {};
}
Praetorian
  • 106,671
  • 19
  • 240
  • 328