
Hello Ovanes, ----- Mensaje original ----- De: Ovanes Markarian <om_boost@keywallet.com> Fecha: Lunes, Agosto 20, 2007 1:35 pm Asunto: [Boost-users] [boost::multi-index] improvement suggestion Para: boost-users@lists.boost.org
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