我有兴趣构建std::unordered_map< K, V> Map;
,其中V与Map::iterator
类似。具体来说,我希望将此vector< Pair< double, Map::iterator> >;
作为V。如上所述,这是C ++中的递归类型,标准不允许。
但是,begin()
,end()
和operator++()
对unordered_map的操作不需要明确定义Map::mapped_type
的任何知识,因此,原则上它似乎应该能够独立于unordered_map定义Map::iterator
。
所以我想知道有没有办法定义:
typedef std::unordered_map_iterator< K> iterator;
typedef std::unordered_map_const_iterator< K> const_iterator;
然后创建:
typedef std::unordored_map< K, iterator> Map;
这样,map.insert( std::make_pair( K(), map.begin());
有意义吗?
例如,如下所示?
typedef std::unordered_map< K, V> Premap;
typedef std::unordered_map< K, Premap::iterator> Map;
在部分答案中,上述建议会产生模板推断错误,如预期的那样。但是,这样的事情应该是可行的。
#include <unordered_map>
#include <iostream>
#include <string>
#include <utility>
typedef std::string K; //these two types are arbitrary
typedef double V; //chosen just for completeness sake.
typedef std::unordered_map< K, V> Premap;
typedef std::unordered_map< K, Premap::iterator> Map;
int main( int argc, char ** argv){
Map test;
test.insert( std::make_pair( std::string( "foo"), test.end()));
return 0;
}
答案 0 :(得分:0)
创建一个包含迭代器的标准容器是不可能的。但是,有其他方法表现相同。
unordered_map
需要唯一键。因此,只需使用std::string
作为值类型,并在必要时在地图中查找。在两种情况下,查找的平均算法复杂度都是相同的 - O(1)。
示例:假设您要表示此数据:
foo -> bar
bar -> baz
baz -> barney
fred -> (nothing)
barney -> (nothing)
然后你会写这个来构建数据结构:
std::unordered_map<std::string, std::string> Map;
Map m;
m.insert(std::make_pair(std::string("foo"), std::string("bar")));
m.insert(std::make_pair(std::string("bar"), std::string("baz")));
m.insert(std::make_pair(std::string("baz"), std::string("barney")));
m.insert(std::make_pair(std::string("fred"), std::string("")));
m.insert(std::make_pair(std::string("barney"), std::string("")));
要沿着此结构中的链走,您可以使用以下代码:
Map::iterator i = m.find("foo");
while (i != m.end() && !i->second.empty()) {
i = m.find(i->second);
}
请注意,任何未显示为键的字符串都可用于标记链的末尾。
使用boost::ptr_unordered_set
并将指针存储到值本身的下一个值。添加适当的相等和比较运算符,以便在集合中忽略指针。请注意,这会增加额外的间接级别,但这是不可避免的。
struct ChainElement
: boost::equality_comparable<ChainElement>
{
std::string key;
ChainElement *next;
ChainElement(std::string const &k, ChainElement *n = NULL)
: key(k), next(n)
{}
bool operator==(ChainElement const &other) const {
return key == other.key;
}
};
namespace std {
template <>
hash<ChainElement>::operator()(ChainElement const &ce) const {
return std::hash(ce.key);
};
}
设置结构,例如像这样:
#include <boost/ptr_container/ptr_unordered_set.hpp>
// ...
boost::ptr_unordered_set<ChainElement> m;
m.insert(new ChainElement("foo"));
m.insert(new ChainElement("bar"));
m.insert(new ChainElement("baz"));
m.insert(new ChainElement("fred"));
m.insert(new ChainElement("barney"));
m.find("foo")->next = &*m.find("bar");
m.find("bar")->next = &*m.find("baz");
m.find("baz")->next = &*m.find("barney");
然后走结构:
ChainElement *elem = &*m.find("foo");
while (elem != NULL) {
// do something
elem = elem->next;
}
使用boost::ptr_unordered_set
而不是std::unordered_set
可以保证删除包含它们的容器时删除对象。