Boost logo

Boost Users :

From: JOAQUIN LOPEZ MU?Z (joaquin_at_[hidden])
Date: 2007-03-21 15:40:54


----- Mensaje original -----
De: "JOAQUIN LOPEZ MU?Z" <joaquin_at_[hidden]>
Fecha: Miércoles, Marzo 21, 2007 8:33 pm
Asunto: Re: [Boost-users] [multi_index] problem with hashed index
Para: boost-users_at_[hidden]

> Hi Boris,
>
> ----- Mensaje original -----
> De: Boris <boriss_at_[hidden]>
> Fecha: Miércoles, Marzo 21, 2007 8:19 pm
> Asunto: [Boost-users] [multi_index] problem with hashed index
> Para: boost-users_at_[hidden]
>
> > I've been using Boost Multiindex quite a lot but don't
> understand
> > why the code below inserts two items. The container has a unique
> > hash index and the two items return the same hash value. Is this
> > is a bug in the library or in my code?
> [...]
> > indexed_by<hashed_unique<identity<shared_ptr<foo> > > >
>
> Here's the problem: your key is shared_ptr<foo>, i.e.,
> you compare *the pointers* rather than the pointed to
> foo objects. What you want is this instead:
>
> indexed_by<hashed_unique<identity<foo > > >

Hi again, I answered too fast, the answer above is more or
less correct but there's more to it: you have overloaded
hash_value for shared_ptr<foo>s so as to use the pointed
to foo objects:

  std::size_t hash_value(const shared_ptr<foo> &f)
  {
  std::size_t seed = 0;
  boost::hash_combine(seed, f->i);
  boost::hash_combine(seed, f->j);
  return seed;
  }

So far so good; but the hashed index depends not only on the
hash functor, but also on an equality predicate, which is
by default (in this case)

  std::equal_to<shared_ptr<foo> >,

which compares pointers, not foo objects. Hence the problem.
Rather than overloading std::equal_to<shared_ptr<foo> >,
which breaks the natural equality semantics of shared_ptr,
my advice is that you change the key of the hashed index
to:

  indexed_by<hashed_unique<identity<foo > > >

as suggested in my previous post, and write the overload
of hash_value for foo, not for shared_ptr<foo>:

std::size_t hash_value(const foo &f)
{
std::size_t seed = 0;
boost::hash_combine(seed, f.i);
boost::hash_combine(seed, f.j);
return seed;
}

Does this work? Please report back,

Joaquín M López Muñoz
Telefónica, Investigación y Desarrollo


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net