The issue is a side effect of Glib::RefPtr<T>:
- declaring operators == and !=
- declaring operator bool()
- not declaring operators <, <=, >, >=
The operators == and != compare pointers for equality and work as expected. The operator bool() is defined to allow the following usage of a RefPtr:
if (ref_ptr)
puts("is non-null");
else
puts("is null");
STL sorted containers need operator< on the type they contain. Assuming p1 and p2 are of type Glib::RefPtr<T>, the following compiles just fine:
p1 < p2
This in turn means that e.g. std::set<Glib::RefPtr<T> > my_map; compiles. Unfortunately, with current version of glibmm, this breaks badly at runtime.
Why? As there's no custom operator<, the compiler interprets p1 < p2 like this:
(bool)p1 < (bool)p2
This is true iff p1 is NULL and p2 is non-NULL. The operators <=, >, >= also work on the results of operator bool(). So, depending on the pointers wrapped in p1 and p2, it's possible that the following would be true:
p1 != p2 && !(p1 < p2) && !(p1 > p2)
(this is true iff p1 and p2 wrap two different non-NULL pointers)
There's a bug report for the issue.
A workaround for the time being is to use a custom comparator like this:
template<typename T>
class RefPtrLess
{
public:
bool operator() (const Glib::RefPtr<T> &a,
const Glib::RefPtr<T> &b)
{
const T* const a_ptr = a.operator->();
const T* const b_ptr = b.operator->();
return a_ptr < b_ptr;
}
};
typedef std::set<Glib::RefPtr<MyType>, RefPtrLess<MyType> > TMyTypeSet;
No comments:
Post a Comment