如何通过hash匹配boost multiindex容器中的nocase-string



查看下面的代码,我为nocase--string键(const-char*(重载了hash函数和string equal函数,但结果不是我所期望的:主函数将打印不到,如何使其匹配?

struct hash_c_string
{
std::size_t operator()(const char *ctx) const
{
return MurmurHash2(ctx, strlen(ctx),static_cast<size_t>(0xc70f6907UL));
}
};
typedef struct  {
const char * name;
}PortMapConfig;
struct by_name{};
struct CompareEqual
{   
inline bool operator()(const char* left, const char* right) const
{
return strcasecmp(left, right)==0;
}
};
using namespace boost::multi_index;

typedef
boost::multi_index_container<
PortMapConfig,
indexed_by<
hashed_unique<tag<by_name>, member<PortMapConfig, const char *, &PortMapConfig::name>, hash_c_string, CompareEqual>
>
> StuContainer;
int main() {
StuContainer con;
PortMapConfig st1 = {"Uplink0"};
con.insert(st1);
auto &indexofName = con.get<by_name>();
const char * s = "uplink0";
auto itr = indexofName.find(s);
if(itr != indexofName.end()){
std::cout << "name:"<<itr->name << std::endl;
}
else
std::cout << "not found!!!"<< std::endl;

return 0;
}

您正试图通过派生属性进行散列,即大小写折叠名称。

即使做得好,这也会很昂贵。这里的所有信号都表明,您可能是以性能的名义进行这些操作的。如果你需要不区分大小写的查找,我建议具体化一个要索引的键,这样你就可以对它们进行自然散列和相等。

重要的是,正如评论者已经指出的,您的解决方案具有未定义的行为,因为哈希/等式函数不同意

您甚至可以预先折叠查找键以避免重复操作。

在这个例子中,我强烈建议使用字符串视图,考虑到根本不进行哈希处理(你有没有用负载因子对其进行过分析?(。

让你的样品发挥作用,还清理了一点:

在Coliru上直播

#include <boost/locale.hpp>
#include <boost/locale/conversion.hpp>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index_container.hpp>
#include <iostream>
namespace bmi = boost::multi_index;
static auto inline fold_case(std::string_view sv) {
return boost::locale::fold_case(sv.data());
}
struct PortMapConfig {
/*explicit*/ PortMapConfig(std::string_view name): name(name) {}
std::string_view name;
std::string name_key = fold_case(name);
struct Hash {
std::size_t operator()(std::string_view sv) const {
return boost::hash_value(sv); // TODO(sehe): murmur instead
}
};
using Equal = std::equal_to<std::string_view>;
};
using StuContainer = bmi::multi_index_container<
PortMapConfig,
bmi::indexed_by<bmi::hashed_unique<
bmi::tag<struct by_name>,
bmi::member<PortMapConfig, std::string, &PortMapConfig::name_key>,
PortMapConfig::Hash,
PortMapConfig::Equal>
>>;
int main() {
std::locale::global(boost::locale::generator()("en_US.UTF-8"));
StuContainer con { {"Uplink0"}, {"Uplink1"} };
if (auto itr = con.find(fold_case("uplink1")); itr != con.end()) {
std::cout << "name:" << itr->name << " (" << itr->name_key << ")n";
}
}

打印

name:Uplink1 (uplink1)

最新更新