我有以下代码:
#include <boost/bimap/bimap.hpp>
#include <boost/bimap/unordered_multiset_of.hpp>
#include <string>
using namespace boost::bimaps;
using namespace boost;
struct Example
{
uint64_t id;
};
struct ExampleHash
{
uint64_t operator()(const Example& item) const
{
return item.id;
}
uint64_t operator()(const uint64_t item) const
{
return item;
}
};
struct ExampleEq
{
bool operator()(const Example& l, const Example& r) const
{
return l.id == r.id;
}
bool operator()(const uint64_t l, const Example& r) const
{
return l == r.id;
}
bool operator()(const Example& l, const uint64_t r) const
{
return operator()(r, l);
}
};
using BM = bimaps::bimap<
unordered_multiset_of<std::string>,
unordered_multiset_of<Example, ExampleHash, ExampleEq>
>;
int main() {
BM bm;
bm.insert(BM::value_type("First", Example{1}));
auto it = bm.right.find(1u);
return 0;
}
template< class CompatibleKey >
iterator find(const CompatibleKey & x);
类型CompatibleKey被认为是(Hash,Pred)的兼容键,如果(CompatibleKey,Hash,Pred)是(Hash,Pred)的兼容扩展。这意味着Hash和Pred接受类型为CompatibleKey的参数,这通常意味着它们具有相应的operator()成员函数的多个重载。
所以我认为auto it = bm.right.find(1u);
会起作用。不幸的是,这会产生编译错误:
error: no match for call to (boost::bimaps::container_adaptor::detail::key_to_base_identity<Example, const Example>) (const long unsigned int&)
我的问题是,是否甚至可以使用不同于bimap键类型的不同类型的CompatibleKey?我已经尝试过检查提升标题,不幸的是,这个标题太复杂了,我无法理解正在发生的事情。
答案 0 :(得分:0)
我同意您的阅读说明似乎表示应该允许此用法。
然而,在长读取和测试之后,我无法看到代码如何实际支持它。更重要的是,有这个签名:
template< class CompatibleKey >
bool replace_key(iterator position, const CompatibleKey & x);
根据其文档要求“CompatibleKey可以分配给key_type”。这与之前看到的“最低要求”明显矛盾。
在得出结论显然它无法发挥作用之后,我记得以前看过同样的事情......:
WONTFIX 为了处理散列索引的兼容键,您需要 不仅透明的平等比较,而且还有某种 透明哈希算子,如
struct generic_hash { template<typename T> std::size_t operator()(const T& x)const { boost::hash<T> h; return h(x); } };
但使用它是棘手的(并且很危险):
multi_index_container< std::string, indexed_by< hashed_unique<identity<std::string>,generic_hash,std::less<void>> > > c{"hello"}; std::cout<<*(c.find("hello"))<<"\n"; // crash
问题的原因是:散列
std::string
不会产生 相同的值已经散列了一个const char *,所以c.find("hello")
会这样做 找不到字符串"hello"
。这就是N3657仅适用于的原因 关联容器并没有扩展到无序 关联容器。关于
std::less<void>
,我对你的建议表示同情,但愿意 更愿意符合标准,这决定了std::less<void>
由用户明确提供而不是 默认。
我有点不好意思在2014年找到我自己的评论:)
答案 1 :(得分:0)
我不知道Boost.Bimap,但使用Boost.MultiIndex的等效构造按预期工作:
<强> Live On Coliru 强>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/member.hpp>
#include <iostream>
#include <string>
#include <utility>
using namespace boost::multi_index;
using namespace boost;
struct Example
{
uint64_t id;
};
struct ExampleHash
{
uint64_t operator()(const Example& item) const
{
return item.id;
}
uint64_t operator()(const uint64_t item) const
{
return item;
}
};
struct ExampleEq
{
bool operator()(const Example& l, const Example& r) const
{
return l.id == r.id;
}
bool operator()(const uint64_t l, const Example& r) const
{
return l == r.id;
}
bool operator()(const Example& l, const uint64_t r) const
{
return operator()(r, l);
}
};
using BM_value_type=std::pair<std::string,Example>;
using BM = multi_index_container<
BM_value_type,
indexed_by<
hashed_non_unique<member<BM_value_type, std::string, &BM_value_type::first>>,
hashed_non_unique<
member<BM_value_type,Example,&BM_value_type::second>,
ExampleHash,ExampleEq
>
>
>;
int main() {
BM bm;
bm.insert(BM::value_type("First", Example{1}));
auto it = bm.get<1>().find(1u);
std::cout<<it->second.id<<"\n"; // 1
return 0;
}
你可能想用Boost.Bimap提交一张票(这对我来说肯定是个错误)。