Взаимная зависимость шаблона С++?
-
09-12-2019 - |
Вопрос
Я хотел бы иметь две структуры, которые указывают друг на друга.В частности, мне хотелось бы иметь следующее:
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, но я пытаюсь сделать все правильно :)
Спасибо!
Решение
Хотя я подозревал, что это может быть дубликат (и во многих отношениях), «ура и ед. - Альф» - это правильно, указывая, что потенциальный дубликат вопрос был конкретно об использовании 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, это может быть объявлено вперед.
Другие советы
К сожалению, это невозможно в том смысле, в котором вы это выражаете.
С другой стороны, мне кажется, что (учитывая ваши требования) можно было бы перевернуть хранилище.
Что, если бы вы использовали list
принадлежащий Values
, а потом карта указывала на этот список?
Это сломало бы циклическую зависимость.
typedef std::list< std::pair<Key, Value> > ListType;
typedef std::multiset<typename ListType::iterator, CmpFirst> MapType;
(Не уверен, что я действительно понял, чего вы пытались достичь...)
Другое решение, которое вам, вероятно, следует рассмотреть, — это посмотреть, можете ли вы выразить это в терминах Boost.MultiIndex.Когда необходимо несколько итераций/шаблонов поиска, Boost.MultiIndex часто является лучшей альтернативой, чем решение, созданное вручную, поскольку оно чередует индексы внутри значений, чтобы минимизировать объем памяти.Плюс согласованность (т. е. наличие всех индексов, ссылающихся на один и тот же набор элементов) является само собой разумеющимся.