
René Haber ha escrito:
Hello,
I'm looking for an easy way to iterate over a set by a user selected index. A little example: [code] struct Person { std::string name; std::string city; };
struct city{}; struct name{};
typedef multi_index_container< Person, indexed_by< ordered_unique< tag<name>, member
>, ordered_non_unique< tag<city>, member > person_set;
typedef Person::index<name>::type Person_by_name; typedef Person::index<city>::type Person_by_city;
person_set persons;
for(Person_by_name::iterator it = persons.get<name>().begin(); .....) {...} [/code]
This for loop is hard-coded to iterate over the set sorted by name. How can I dynamically change the iterator used in this loop to let the user decide the sort criteria?
Hello René, As Matías states on his reply, maybe a simple switch could be enough for your needs. Otherwise, you'll have to devise some kind of dynamic framework that lets you add run-time polymorphism to the multi-index container (which is basically a compile-time construct.) This is simple in principle, but the implementation can be a little cumbersome for those unfamiliar with MPL and so-called type erasure techniques. I've written a small example for your convenience that lets you iterate over any index selected at run time, let me go through the ideas step by step: The first place where dynamic polymorphism must be added is the iterator itself: as the iterator type of index #N is *not* the same as that of index #M, you cannot possibly have a loop that handles both types of iterators uniformly. There is an Adobe open source library called ASL that provides a nice utility called adobe::any_iterator: http://opensource.adobe.com/classadobe_1_1any__iterator.html adobe::any_iterator basically accepts any conforming iterator type object at construction time and wraps it with a polymorphic interface so that code using adobe::any_iterator's can through the provided extra indirection layer actually use iterators of different types --precisely what we want. adobe::any_iterator is conceptually very similar to boost::function, which can effectively hide under the same interface callable objects of entirely different types. So, we use adobe::any_iterator to define: template<typename MultiIndexContainer> struct multi_index_any_iterator { typedef typename adobe::any_iterator< const typename MultiIndexContainer::value_type, std::bidirectional_iterator_tag
type; };
template<typename MultiIndexContainer>
struct multi_index_any_iterator_pair
{
typedef typename multi_index_any_iterator<
MultiIndexContainer>::type iterator;
typedef std::pair
person_set;
int main()
{
person_set ps;
ps.insert(person("Leonardo","Vinci"));
ps.insert(person("Aristotle","Stagira"));
ps.insert(person("Leibniz","Leipzig"));
ps.insert(person("Cervantes","Alcala"));
std::cout<<"0=name, 1=city: ";
int n;
std::cin>>n;
multi_index_any_iterator_pair