需要一个C ++映射和列表,其中包含彼此的迭代器

问题描述

我有一个自定义模板容器,使用的地图和列表保持同步。地图需要保存MyList :: const_iterator,而列表需要保存MyMap :: const_iterator。我能够找到的唯一解决方案是对一个迭代器进行双打,如下例所示。

是否有转发此声明的正确方法,这样我就不需要丑陋的修饰了?

可运行的代码,位于http://coliru.stacked-crooked.com/a/a5eae03ad5090b27

(肯定还有其他方法可用于该示例,但这超出了范围。这是一个较大程序的摘录。我只是想在没有UB的情况下做出“圆形”定义。 )

#include <iostream>
#include <list>
#include <unordered_map>

template<class ObjectT> class MyClass
{
private:
// SUMMARY: The map must contain an iterator to the list,and the list must contain an iterator to the map.
// I have not been able to figure out how to define that (circular),so I've punned an iterator to a different list for the map entry.
    typedef std::list<ObjectT> PunnedList;

    struct MapEntry
    {
        ObjectT m_object;
        mutable typename PunnedList::const_iterator m_listIt; // Really a List::const_iterator,but that can't be defined.
    };

    typedef std::unordered_multimap<std::string,MapEntry> Map;

public:
    struct ListEntry
    {
        typename Map::iterator m_mapIt;

        const ObjectT& object() const
        {
            return m_mapIt->second.m_object;
        }

        const std::string& name() const
        {
            return m_mapIt->first;
        }

    };
private:
    typedef std::list<ListEntry> List;

    Map mMap;
    List mList;

private:
    typename List::const_iterator listiter_from_mapiter( typename Map::const_iterator& miter ) const
    {
        static_assert(sizeof(typename PunnedList::const_iterator) == sizeof(typename List::const_iterator));
        return *(reinterpret_cast<typename List::const_iterator*>(&miter->second.m_listIt));
    }

public:
    
    typename List::const_iterator append( const std::string &name,const ObjectT& item )
    {
        static_assert(sizeof(typename PunnedList::const_iterator) == sizeof(typename List::const_iterator));

        MapEntry entry{ item,typename PunnedList::const_iterator{} };

        auto mapIter = mMap.insert({ name,entry });
        mList.push_back({ mapIter });
        auto iter = mList.cend();
        --iter;
        *(reinterpret_cast<typename List::const_iterator*>(&mapIter->second.m_listIt)) = iter;
        return iter;
    }
    
    typename List::const_iterator begin() const
    {
        return mList.end();
    }

    typename List::const_iterator end() const
    {
        return mList.end();
    }

    void erase( typename List::const_iterator iter )
    {
        mMap.erase(iter->m_mapIt);
        mList.erase( iter );
    }

    typename List::const_iterator find( const std::string &name ) const
    {
        auto range = mMap.equal_range(name);

        for (auto mapIter = range.first; mapIter != range.second; ++mapIter)
        {
            // In the real program,there are additional criteria on the map entry,not needed for the example.
            // if (mapIter is a match)
                return listiter_from_mapiter(mapIter);
        }

         return mList.cend();
    }
};

int main()
{
    MyClass<int> container;
    container.append("A",1);
    container.append("B",2);
    container.append("C",1);
    
    std::cout << container.find("B")->object();
}

解决方法

向前声明至少一个内部类会中断该循环:

template<class ObjectT> class MyClass
{
public:
    struct ListEntry;
private:
    typedef std::list<ListEntry> List;

    // Rest of the class,using List as you like

请注意,由于List::const_iterator不需要实例化std::list<T>,因此以下T可以正常工作。

,

不可能声明依赖于类型T的类型Y,该类型也依赖于T。但是您可以使用包装器来做到这一点:

(似乎您要创建一个哈希表,其中的元素按插入顺序排列?通常的做法是包装该元素和一个链表的迭代器。)

#include <string>
#include <list>
#include <unordered_map>


template<typename T>
class A{
    struct Wrapper;
    typedef std::unordered_multimap<std::string,Wrapper> Map;
    typedef typename Map::const_iterator map_iter;
    typedef std::list<map_iter> List;
    typedef typename List::const_iterator list_iter;
    struct Wrapper{
        T value;
        list_iter iter;
    };
    Map map;
    List list;
public:
    // do what you want
};

它之所以有效,是因为声明std::unordered_multimap<std::string,Wrapper>::iterator并不需要定义Wrapper(此处无需实例化)。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...