Подтвердить что ты не робот

STL-карта на себя?

Я хотел бы создать std::map, который содержит итераторы std::vector для себя, для реализации простой структуры графства на основе смежности.

Однако объявление типа имеет тупик: кажется, вам нужно определение всего типа карты, чтобы получить тип итератора указанной карты, например:

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

Есть ли какой-то тип итератора частичного отображения, который я могу получить только с типом ключа, поэтому я могу объявить полную карту?

4b9b3361

Ответ 1

Вы можете использовать форвардное объявление нового типа.

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

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

С этой косвенностью компилятор должен позволить вам с этим справиться. Это не очень мило, но, честно говоря, я не думаю, что вы можете легко сломать себе ссылку.

Ответ 2

Не слишком уродливо, учитывая...

Это работает в GCC 4.0.1 и отлично компилируется в жестком режиме Comeau.

Определения шаблонов анализируются и откладываются до тех пор, пока они не будут созданы. Компилятор даже не видит, что такое rec_map_iterator, пока не наступит время его создания, и к тому времени он знает, как это сделать: 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 > > > {};

Здесь была использована тестовая программа.

#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;
}

Ответ 3

Мне не нравилось получение из контейнера в моем предыдущем ответе, так что вот альтернатива:

template< class key >
struct rec_map_gen {
    struct i;
    typedef map< key, vector< i > > t;
    struct i : t::iterator {
        i( typename t::iterator v )
        : t::iterator(v) {}
    };
};

Теперь вы должны использовать rec_map_gen<int>::t, rec_map_gen<int>::t::iterator и т.д., но у вас также есть доступ ко всем конструкторам std::map. Слишком плохо С++ не позволяет шаблонам шаблонов.

Использование производного типа итератора должно быть ОК. Вы все равно можете инициализировать обратный итератор из элемента этой структуры, например.

Ответ 4

В дополнение к ответу на Potatoswatter, если вы не возражаете ссылаться на весь шаблонный тип карты несколько раз, вам нужно только подклассифицировать итератор и не нуждаться в каких-либо предварительных объявлениях:

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

Затем используйте полный тип:

map<int, vector<rec_map_iterator<int>>> m;

Кроме того, здесь обновление (мое любимое до сих пор) для С++ 11, объявив rec_map как псевдоним, который можно настроить:

template<class key>
struct rec_map_iterator;

template<class key>
using rec_map = map<key, vector<rec_map_iterator<key>>>;

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)
    {}
};

Это работает так же, как версия Potatoswatter:

rec_map<int> my_map;