c++ - 如何通过哈希匹配boost multi_index_container中的nocase c字符串

标签 c++ boost multi-index

看看下面的代码,我为nocase-c-string键(const char *)重载了哈希函数和字符串等于函数,但是结果却不是我所期望的:找不到主函数,如何使其匹配?

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

最佳答案

您正在尝试通过派生属性(即大小写折叠的名称)进行哈希处理。
即使做对了¹,这也会很昂贵。这里的所有信号都表明您可能以性能为名进行这些操作。如果您需要不区分大小写的查找,建议您修改要索引的键,这样就可以在它们上具有自然的哈希值和相等性。

¹ Importantly, as the commenter already points out, your solution has Undefined Behaviour because the hash/equality functions don't agree


您甚至可以预折叠查找键,以避免重复工作。
在此示例中,我强烈建议使用字符串 View ,考虑根本不要使用散列(是否已使用负载因子对其进行了剖析?)。
使您的示例工作,并进行一些清理:
Live On 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)

关于c++ - 如何通过哈希匹配boost multi_index_container中的nocase c字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63137352/

相关文章:

python - 在日期为 "close"的级别上重新索引 MultiIndex

c++ - 移植程序,好奇 int16_t & __int16 是不是 'the same'

c++ - 我的逻辑正确吗?它给出了段错误

c++ - 继承和重载默认构造函数

c++ - 如何通过 C++ boost::serialization 对 std::map 进行部分反序列化

python - 检索 pandas 中 MultiIndex 的一级值

c++ - 在第二次调用中生成不同的随机数

c++ - 一旦你采用了 boost 的智能指针,有没有使用原始指针的情况?

C++ 内存映射文件(boost::interprocess)可以在程序执行期间移动吗?

python - 将 Panda DataFrame 转换为类面板结构