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