[odb-users] std::set<odb::lazy_shared_ptr<foo>> fails
Boris Kolpackov
boris at codesynthesis.com
Sun Aug 19 10:26:37 EDT 2012
Hi Miguel,
Miguel Revilla Rodríguez <yo at miguelrevilla.com> writes:
> I'm trying to declare an object with a
> std::set<odb::lazy_shared_ptr<foo>> member, and while the odb compiler
> works nicely on it and doesn't complain, later the generated code
> (object-odb.cpp) fails to compile with G++ 4.7.1 with options -O2
> -std=c++11.
When reporting that something fails to compile, it is always a good
idea to include the diagnostics from the compiler. Without it we can
only guess what could have gone wrong.
> If I change std::set with std::vector, then everything is fine, but
> I'd prefer to use a set rather than a vector in this case.
My guess is that the compiler complains there is no operator< defined
for odb::lazy_shared_ptr. The reason for this is that it is tricky to
come up with a universally-acceptable semantics. For example:
1. How do we compare a transient object to a persistent one? Do
we use the underlying pointers and if so what about unloaded
pointers? Do we use object ids?
2. When comparing unloaded persistent objects, do we take into
account the database?
However, if you have some application-specific knowledge that
allows you to provide a sensible less-than comparison, then you
can easily add it as a second template argument to std::set.
For example, if you know that all the objects in your set will
be non-NULL and will have valid object ids (i.e., no object with
yet unassigned auto id will ever be added to the set), and they
will also be from the same database, then you can define an id-
based comparison:
template <typename T>
struct object_id_comparator
{
bool operator (const odb::lazy_shared_ptr<T>& x,
const odb::lazy_shared_ptr<T>& y) const
{
return x.object_id<T> () < y.object_id<T> ();
}
};
Then, in your persistent class, you can have:
std::set<odb::lazy_shared_ptr<foo>, object_id_comparator<foo>> foo_;
Boris
More information about the odb-users
mailing list