Boost logo

Boost Users :

From: JOAQUIN LOPEZ MU?Z (joaquin_at_[hidden])
Date: 2007-08-21 06:58:50


Hello Ovanes,

----- Mensaje original -----
De: Ovanes Markarian <om_boost_at_[hidden]>
Fecha: Lunes, Agosto 20, 2007 1:35 pm
Asunto: [Boost-users] [boost::multi-index] improvement suggestion
Para: boost-users_at_[hidden]

> Hello all,
>
> working with boost multi-index container requires sometimes some
> effort in regards of correct tagging (or at least some typing
> work ;). I found the following approach to be useful and may be
> it can be integrated in the multi-index library.
>
> First of all the dealing with searchable collections (STL
> collections are no exception) can be really nasty in regards of
> finding an iterator and comparing it with the end iterator. The
> following function can really be of help:
>
[...]
> template<class T, class K>
> inline boost::iterator_range<typename T::const_iterator>
> find_range(T const& container, K const& key)
> {
> return
> boost::make_iterator_range(
> container.find(key),container.end());
> }
>
> //non-const version follows as well ...
>
> Actually iterator_range defines a "bool"- and "!"- (NOT) operators.
> iterator_range is returned by this function. Therefore constructs
> like:
> std::set<std::string> some_set;
>
> if(!find_range(some_set, "my_key"))
> some_set.insert("my_key");
>
> are possible without the need of accesing the underlying iterator
> types or explicitly comparing the found iterator with the end
> iterator.

I've got some doubts about your construct:

1. The syntax to check whether a value has been found or not is
certainly clearer, but at the expense of a more convoluted
expression to get the value found:

    const std::string& v=
        *boost::begin(find_range(some_set,"my_key"));

And the type of the construct returned by find_range is also somewhat
messy to type down (at least until compilers come with decltype and
auto):

    boost::iterator_range<std::set<std::string>::const_iterator> r=
      find_range(...);

2. If, given the complexities associated to getting the value with
find_range, you propose it only as a way to verify whether the value
exists, there are simpler alternatives which do not use Boost.Range:

    template<class T,class K>
    bool there_exists(T const& container, K const& key)
    {
      return container.find(key)!=container.end();
    }

3. find_range does return a range, but this range is in no
sensible way related to the key passed, except that its
first element, if the range is not void, contains the key.
But the rest of the elements have nothing to do with the key,
and what is worse, elements with the key might not be
contained in the range, since find does not guarantee that
the element found is the first one with the key.

4. So, if you want a concise syntax to determine whether
an element is found or not, plus simple access to this element,
maybe you can write an utility of your own exactly suited
to this task, rather than relying on Boost.Range. I'm thinking
about something like this:

    // locator can be pointing to an element or not. If the
    // former, dereferencing it is legal.

    template<typename Container>
    struct locator
    {
      typedef typename Container::value_type;
      operator bool()const;
      bool operator!()const;
      const value_type& operator*()const;
      ...
    };

    template<class T,class K>
    locator<T> find(T const& container, K const& key)
    {
      ...
    }

Don't you find this more convenient?

>
> The next step dealing with Multi-Index container turned out in
> multipletypedefs for every tagged type. The main disadvantage in
> this approach was to constantly retrieve the required container
> view and related iterator, so I came up the the following class:
[...]

This also could benefit of a more specific locator-based interface,
IMHO.

Best,

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