Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Find a raw pointer in a bimap of smart pointers

I need to be able to search for a raw pointer Thing* in a boost::bimap<shared_ptr<Thing>, int>. However, I can't call a function with the signature bm.left.find(thingRawPtr) because a smart pointer cannot be implicitly constructed from a raw pointer:

bimap<shared_ptr<Thing>, int> bm;

void f(Thing* thing)
{
    bm.left.find(thing); // (Nasty) compile error
}

What's the best way to circumvent this?

like image 519
George Hilliard Avatar asked Mar 27 '14 17:03

George Hilliard


1 Answers

You have to create a smart pointer, but you can't do it the regular way, because then you would have two separately created smart pointers managing one object, and when one pointer decides to delete the Thing, the other pointer is left with a dangling pointer.

To get around this, you can create a shared_ptr with a do-nothing deleter. This is a functor that will do nothing instead of delete the object like the smart pointer wants it to. Here's a simple deleter from Boost's docs:

struct null_deleter
{
    void operator()(void const *) const
    {
    }
};

Now your code becomes:

void f(Thing* thing)
{
    bm.left.find(shared_ptr<Thing>(thing, null_deleter)); // compiles
}

But! We're using C++11, which has a handy feature called lambdas, or anonymous functions. You can use it to unclutter your code from one-off functors such as null_deleter. Using lambdas, everything above can be replaced with:

void f(Thing* thing)
{
    bm.left.find(shared_ptr<Thing>(thing, [](void*){}));
    // doesn't need null_deleter anywhere!
}
like image 82
George Hilliard Avatar answered Sep 22 '22 04:09

George Hilliard