Boost logo

Boost Users :

From: Ovanes Markarian (om_boost_at_[hidden])
Date: 2007-08-20 07:34:08


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 function to dermine if the container contains the key
specified
    /// @param T - container type
    /// @param K - key type
    /// @param container - container to search for a key
    /// @param key - key to be found in the container
    /// \return iterator_range containing the begin and end iterator of the
found key. begin iterator equals end iterator the range is empty => nothing
found
    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.

The next step dealing with Multi-Index container turned out in multiple
typedefs 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:

    /// helper class used to retrieve multi-index values dependent on the
view tag
    template<class Tag_, class MultiIndex_>
    struct value_retrieval
    {
        /// type definition used to produce tag dependent view
        typedef typename MultiIndex_::index<Tag_>::type
view_type;
        /// type definition for the const iterator through the view
        typedef typename view_type::const_iterator
citer_type;
        /// iterator range used to represent the result
        typedef boost::iterator_range<citer_type>
result_type;

        /// initializing ctor
        /// initializes the contained view by using the specified Tag_ type
        value_retrieval(MultiIndex_ const& mi)
            : view_(mi.get<Tag_>())
        {}

        /// find a type at the key specified
        /// @param LookUpType_ - key type
        /// @param key - key instance to be found
        template<class LookUpType_>
        result_type at(LookUpType_ const& key)const
        {
            return find_range(view_, key);
        }

    private:
        /// view reference
        view_type const& view_;
    };

This class deals with constant views, since I did not require changeable
ones, but as one can see the "at"-function can either be used to identify
the found iterator range or just to make a check if such a key exists.
Dealing with this type is more easier, as to define multi-index accessed
view and iterator types.

Sample

typedef multi_index_container
<
    some_type
, indexed_by
    <
       ....
>
> my_container;

typedef value_retrieval<my_container, tag_name> by_name;
typedef value_retrieval<my_container, tag_value> by_value;

//somewhere in code
by_name value_by_name(some_container_inst);
//if typename is required prefix it...
by_name::result_type r = value_by_name.at("some key");
if(r)
   /// do smth with r

Best Regards,
Ovanes



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