Reputation: 53
I have a small segment of code that I need to optimize. Thread 'A' has created a boost shared_ptr to a heap object. Thread 'A' writes the shared_ptr to a thread safe queue. Thread 'B' reads the shared_ptr, uses it, and then destroys it.
Intense profiling/testing proves that the copying of the shared_ptr going in/out of the queue and adjusting reference counts is costly. Therefore, I would like to pass the shared ptr to the queue via reference. I would also like to use std::move to move the shared_ptr into the queue rather than construct a new shared_ptr, (I know this will invalidate the shared_ptr parameter which was passed to the queue).
Everything described works fine until I mix in a dash of polymorphism. I can't pass by ref a shared_ptr to a derived obj to a function expecting a shared_ptr to a base class. I have boiled this down to a very small snip that exposes the behavior that confuses me.
#include <boost/shared_ptr.hpp>
class Base
{
};
class Derived : public Base
{
};
int main()
{
boost::shared_ptr<Derived> pDerived(new Derived()); // simple creation
boost::shared_ptr<Derived> &alias1 = pDerived; // works fine
const boost::shared_ptr<Base> &alias2 = pDerived; // also works fine
boost::shared_ptr<Base> &alias3 = pDerived; // compilation error
//native pointers
Derived *alias4 = pDerived.get(); //works
const Base *alias5 = pDerived.get(); //works
Base *alias6 = pDerived.get(); //works
//native references
Derived &alias7 = *pDerived; // works
const Base &alias8 = *pDerived; // works
Base &alias9 = *pDerived; // works
}
I do not understand why the assignment to alias2 is perfectly fine, yet the assignment to alias3 yields a compiler error. Can someone please explain this? I need functionality like the alias3 example and can't make it work.
Upvotes: 3
Views: 182
Reputation: 1725
This problem is not related to boost or smart pointers. It can happen with POD types too as shown in the following simple example:
int main() {
int x = 0;
const double &y = x; //fine
double &z = x; //error!
return 0;
}
The reason is that a temporary value (rvalue) can bind to a const&
but it cannot bind to a &
. What happens in double &z = x
is that x
and z
are unrelated types, and x
needs to be converted to a double
and a temporary variable is created, which cannot bind to a &
.
Upvotes: 0