Boost logo

Boost :

From: JOAQUIN LOPEZ MU?Z (joaquin_at_[hidden])
Date: 2003-07-12 14:21:27


Hi again,

----- Mensaje Original -----
De: Fernando Cacciola <fcacciola_at_[hidden]>
Fecha: Sábado, Julio 12, 2003 7:32 pm
Asunto: [boost] Re: Re: Interest in multiindex_set?(again)

[stuff about conceptual structure of multtindex_set deleted]

OK, I'm glad we finally got to understand each other :)
There's a problem with the name of the class. Others have expressed
dislike for "multtindex_set". Alternative candidates are "indexed_set"
and "indexed_table". I haven't decided yet for one, plus there's the
problem of which namespace should this live in (regardless of whether
it is promoted to namespace boost later). The alternatives so far
are (name of the class/associated namespace)

* multiindex_set/boost::multiindex
* indexed_set/??
* indexed_table/??
* ??/boost::container (proposed by Daryle)

boost::container I don't like because some of the associated small utility
classes and functions (less_by, get, project) shouldn't really belong into a
general-purpose namespace like container which is supposed to hold other
contributions. Also, there's the additional problem that the class and the
namespace shouldn't be named the same (it makes some compilers choke,
this has been discussed in connection with Boost.Tuple). Suggestions in
this area are most welcome.

> >>
> >> I vote for a separate KeyExtraction because:
> >>

[...]

> Half of it.
> I see that I can use the precanned 'less-by' and specify a
> different comparison semantic (though in this case why is it named
> 'less_by' instead of 'order_by'), but I don't see how can I use it
> with something different than a data member as the key
> itself. On some applications, specially outside databases, the
> keys are given by runtime expressions and not just stored data
> members.
> If the users would have to end up writting their own predicates,
> the separaton will make that task a lot easier.
>

At first I was strongly against key extraction, but now I got an idea
that maybe we all can settle for. Following Beman's advice, I elminated
the "unique_indices" parameter in favor of this type of specification:

  multiindex_set<
    employee,
    tuple<
      unique<std::less<employee> >,
      non_unique<less_by<employee,std::string,&employee::name> >,
      non_unique<less_by<employee,int,&employee::age> > > >
  employee_set;

unique and non-unique accepts the comparison predicate as a template
parameter. This is nicer in which it opens the way to other index implementations
(hashed indices, for instance) in a seamless manner.
Now, I see this new style lends itself more easily to a key extraction approach.
Instead of accepting a comparison predicate, it can be changed to:

  unique<KeyExtractor,Compare=std::less<typename KeyExtractor::result_type> >

where KeyExtractor is expected to behave as an std::unary_function and hence
have a result_type nested typedef. If we drop less_by and provide a "member"
utility class, instead of

  non_unique<less_by<employee,std::string,&employee::name> >

we can have

  non_unique<member<employee,std::string,&employee::name> >

and instead of

  non_unique<less_by<employee,std::string,&employee::name,string_case_insensitive_compare> >

we can have

  non_unique<member<employee,std::string,&employee::name>, string_case_insensitive_compare>

Basically, the two schemes are functionally equivalent, but the latter enforces the
key-extraction approach, which seems to have been demanded by Boosters. Moreover,
it accepts the kind of external key-extraction functions you were talking about.

What do you think about it?

[...]
> OK, this is the best we could think of, at least right now.
> Many times the user knows exactly what she's doing so that no
> collisionswill ever really ocurr. For example, if the modify does
> not change keys
> but other data.
> For this cases modify() is a big plus. The acutal user code could
> assertthe result of modify() so that a coallision is treated as
> postconditionviolation.

Here you can even resort to const_casting just as you would with
an std::set. modify is expected to be used mainly when you do not
change unique keys but you change non-unique keys; in this case,
modify will not fail, but internal reordering is necessary (which
bans the use of const_casting).

>
> The documentation could express emphatically that if the modification
> changed keys, update() must be used, else, modify() can.
>
> A possibility is to protect modify() so that it can used but not
> accidentally.That is, we can prevent a user for just seeing
> modify() on the public interface
> and blindly and incorrectly use it.
> Simply putting it into a protected section is problematic because
> it requires the user to derive from the class, so something better
> should be used to protect such a method.
>
> ...but I don't know right know how to code this :-)
> but I'm sure there are patterns for this already.
> Maybe with an addtional 'Modifier' template parameter which
> the user supplies with a 'modify' wrapper, or something like that.
> I'll let you know if I think of something.
>

Plase do so. Best regards,

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


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk