Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

STL map onto itself?

I'd like to create a std::map that contains a std::vector of iterators into itself, to implement a simple adjacency list-based graph structure.

However, the type declaration has me stumped: it would seem you need the entire map type definition to get the iterator type of said map, like so:

map< int, Something >::iterator MyMap_it;  // what should Something be?
map< int, vector<MyMap_it> > MyMap_t;

Is there some sort of partial map iterator type I can get with just the key type, so I can declare the full map?

like image 282
genpfault Avatar asked Sep 10 '09 05:09

genpfault


People also ask

How do I avoid sorting in maps?

The way map is implemented internally, it's not possible for you to prevent keys to be sorted. However, you can maintain an additional list(using vector) to store the order in which keys appear. Later on, iterate over the map and the vector to achieve what you want.

How does the map STL library work?

Maps are associative containers that store elements in a mapped fashion. Each element has a key value and a mapped value. No two mapped values can have the same key values.

Is map part of STL?

​Maps are a part of the C++ STL. Maps are associative containers that store elements in a combination of key values and mapped values that follow a specific order.

Is std :: map balanced?

In fact it is not important which type of a tree is used to implement an std::map. But this tree must provide necessary complexity for insert, erase and some other operations. Basically it means that the tree must be balanced (and, of course, auto-balance itself when elements are inserted into or removed from).


2 Answers

You could use forward declaration of a new type.

class MapItContainers;
typedef map<int, MapItContainers>::iterator MyMap_it;

class MapItContainers
{
public:
 vector<MyMap_it> vec;
};

With this indirection the compiler should let you get away with it. It is not so very pretty but honestly I don't think you can break the self referencing easily.

like image 187
nasmorn Avatar answered Oct 22 '22 01:10

nasmorn


Not too ugly, considering…

This works in GCC 4.0.1 and compiles fine in Comeau strict mode.

The template definitions are parsed and deferred until they're instantiated. The compiler doesn't even see what a rec_map_iterator is until it's time to create one, by which time it knows how to do so ;v) .

template< class key >
struct rec_map;

template< class key >
struct rec_map_iterator : rec_map< key >::iterator {
    rec_map_iterator( typename rec_map< key >::iterator i)
    : rec_map< key >::iterator(i) {}
};

template< class key >
struct rec_map : map< key, vector< rec_map_iterator< key > > > {};

Here's the test program I used.

#include <iostream>
#include <map>
#include <vector>

using namespace std;

template< class key >
struct rec_map;

template< class key >
struct rec_map_iterator : rec_map< key >::iterator {
    rec_map_iterator( typename rec_map< key >::iterator i)
    : rec_map< key >::iterator(i) {}
};

template< class key >
struct rec_map : map< key, vector< rec_map_iterator< key > > > {};

int main( int argc, char ** argv ) {
    rec_map< int > my_map;

    my_map[4];
    my_map[6].push_back( my_map.begin() );

    cerr << my_map[6].front()->first << endl;

    return 0;
}
like image 5
Potatoswatter Avatar answered Oct 22 '22 00:10

Potatoswatter