PDA

View Full Version : Storing boost.shared_ptr in a QVariant



negritot
28th September 2010, 21:05
Hello all. I want to store smart pointers in QVariants for purposes of working with Qt's model/view system. However, it appears that QVariant.operator== doesn't work when the type is a smart pointer. For example:


#include <boost/shared_ptr.hpp>
Q_DECLARE_METATYPE(boost::shared_ptr<int>);
Q_DECLARE_METATYPE(int*);

void testQVariant()
{
int* rawInt = new int(5);
QVariant rawVariant = QVariant::fromValue(rawInt);
QVariant rawVariant2 = QVariant::fromValue(rawInt);
bool equal = rawVariant2 == rawVariant;

boost::shared_ptr<int> smartInt(new int(5));
QVariant smartVariant = QVariant::fromValue(smartInt);
QVariant smartVariant2 = QVariant::fromValue(smartInt);
equal = smartVariant2 == smartVariant;
}

The QVariants are equal when using raw pointers, but not when using smart pointers (boost::shared_ptr in this case, but I see the same behavior with another smart pointer type, as well).

The upshot is that I can store these in a model (as Qt::UserRole data), but I'm unable to ask the model to find them (match() always returns an index of -1). Any ideas?

ChrisW67
29th September 2010, 01:18
boost::shared_ptr<int> smartInt(new int(5));
QVariant smartVariant = QVariant::fromValue(smartInt);
QVariant smartVariant2 = QVariant::fromValue(smartInt);
equal = smartVariant2 == smartVariant;
boost::shared_ptr<int> a = smartVariant.value<boost::shared_ptr<int> >();
boost::shared_ptr<int> b = smartVariant2.value<boost::shared_ptr<int> >();
qDebug() << a.get() << b.get();
qDebug() << a.use_count() << b.use_count();

QVariant has made a copy of your shared_ptr in each of smartVariant and smartVariant2. They are two different smart_ptr objects (with no operator==) so the equality test fails. They do however point to the same shared data (debug line 1). Debug line 2 shows that the shared data is more shared than you think: a reference count of 5 (from smartInt, the two variants, a, and b).

negritot
4th October 2010, 19:51
Thanks, Chris. I wonder if I could implement operator== to get the behavior I want....

ChrisW67
4th October 2010, 23:42
I just revisited the Boost shared_ptr docs. boost::shared_ptr::operator==() does exist and compares the raw pointers as you would expect. The behaviour you are seeing in QVariant is a limitation of the QVariant::operator==() : "In the case of custom types, their equalness operators are not called. Instead the values' addresses are compared." You may be stuck with manually extracting the two shared_ptrs and using them directly in the equality test.