STL 映射到自身?

发布于 2024-08-04 12:26:26 字数 350 浏览 1 评论 0原文

我想创建一个 std::map ,其中包含一个 std::vector 迭代器,以实现一个简单的基于邻接列表的图形结构。

但是,类型声明让我难住了:似乎您需要整个映射类型定义来获取所述映射的迭代器类型,如下所示:

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

是否有某种部分映射迭代器类型我可以仅使用键类型获得,所以我可以声明完整的地图吗?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

坐在坟头思考人生 2024-08-11 12:26:26

您可以使用新类型的前向声明。

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

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

通过这种间接寻址,编译器应该让您摆脱它。
它不是那么漂亮,但老实说,我认为你不能轻易打破自引用。

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.

忆沫 2024-08-11 12:26:26

考虑到……

这在 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;
}

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;
}
厌味 2024-08-11 12:26:26

我不喜欢在之前的答案中从容器中派生,所以这里有一个替代方案:

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::t, rec_map_gen::t::迭代器等,但您还可以访问所有std::map的构造函数。遗憾的是 C++ 不允许将 typedef 模板化。

使用派生迭代器类型应该没问题。例如,您仍然可以从此结构的元素初始化反向迭代器。

I didn't like deriving from a container in my previous answer so here's an alternative:

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

Now you have to use rec_map_gen<int>::t, rec_map_gen<int>::t::iterator, etc, but you also have access to all std::map's constructors. It's too bad C++ doesn't allow typedefs to be templated.

Using a derived iterator type should be OK. You can still initialize a reverse iterator from an element of this structure, for example.

灵芸 2024-08-11 12:26:26

除了 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;

另外,这里是C++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;

In addition to Potatoswatter's answer, if you don't mind having to refer to the entire templated map type multiple times, you only need to subclass the iterator and don't need any pre-declarations:

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

Then use the full type:

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

Also, here's an update (my favorite so far) for C++11 by declaring rec_map as an alias, which can be templated:

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

This works the same as Potatoswatter's version:

rec_map<int> my_map;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文