Взаимная зависимость шаблона C ++? - PullRequest
2 голосов
/ 08 марта 2012

Я хотел бы иметь две структуры, которые указывают друг на друга.В частности, я хотел бы иметь следующее:

template<typename Key, typename Value> 
class MyStructure {
public:
  typedef map<Key, list<pair<Value, typename ListType::iterator>>> MapType;
  typedef list<typename MapType::element_type::iterator> ListType;
private:
  MapType map_;
  ListType list_;
}

Очевидно, это не будет работать, поскольку ListType ранее не объявлялся как тип.Как я мог это сделать?Как вы можете видеть, я использую типы итераторов в качестве указателей на элементы этих двух структур.

Я думал об использовании любопытно повторяющегося шаблона, но не смог ничего с этим поделать.Кто-то на ## c ++ также предложил использовать псевдонимы шаблонов, но это тоже не удалось (по крайней мере, я не знаю, как использовать эту идею).

Я делаю что-то не так, концептуально?Или, может быть, "не в соответствии с концепциями C ++"?Конечно, я мог бы сделать это с помощью void * s, но я пытаюсь сделать все правильно:)

Спасибо!

Ответы [ 2 ]

3 голосов
/ 08 марта 2012

Хотя я подозревал, что это может быть дубликат (и во многих отношениях это так), «Приветствия и hth. - Alf» прав, указывая, что потенциальный дубликат вопроса был конкретно об использовании typedef для такого рода вещи.

Однако в данном вопросе ФП хотел бы знать, как в целом справляться с взаимным включением в сценарий, описанный в вопросе.

Вот предложение:

#include <list>
#include <map>

template <typename Key, typename Value>
class MyElement;

template <typename Key, typename Value>
class MyStructure
{
public:
  typedef std::map<Key,MyElement<Key,Value> > MapType;
  typedef std::list<MyElement<Key,Value> >    ListType;
};

template <typename Key, typename Value>
class MyElement {
public:
  typename MyStructure<Key,Value>::MapType::iterator  map_iterator;
  typename MyStructure<Key,Value>::ListType::iterator list_iterator;
};

Как видите, я ввел новый тип данных MyElement, который содержит итератор списка, а также итератор карты. Поскольку это класс, а не typedef, он может быть объявлен заранее.

0 голосов
/ 08 марта 2012

Это, к сожалению, невозможно, в том виде, как вы это выражаете.

С другой стороны, мне кажется, что (учитывая ваши требования) вы могли бы перевернуть хранилище.

Чтоесли вы использовали list из Values, а затем указали карту на этот список?

Это нарушило бы циклическую зависимость.

typedef std::list< std::pair<Key, Value> > ListType;
typedef std::multiset<typename ListType::iterator, CmpFirst> MapType;

(Не уверен, если яправда, понял, чего вы пытались достичь ...)

Другое решение, которое вам, вероятно, следует рассмотреть, - это посмотреть, сможете ли вы выразить это в терминах Boost.MultiIndex .Когда необходимо несколько итераций / шаблонов поиска, Boost.MultiIndex часто является лучшей альтернативой, чем решение ручной работы, поскольку оно чередует индексы внутри значений, чтобы минимизировать объем хранилища.Плюс согласованность (т. Е. Наличие всех индексов, ссылающихся на один и тот же набор элементов) является заданной.

...