我可以在 boost::multi_index 类哈希接口中使用 lambda 作为哈希函数吗?

Can I use lambda as a hashing function in boost::multi_index hash-like interface?

是否可以在 boost::multi_index 的 hashed_<non>_unique 接口中使用 lambda 进行散列? 看这个例子:https://godbolt.org/z/1voof3

我也看到了这个:How to use lambda function as hash function in unordered_map? 答案是:

You need to pass lambda object to unordered_map constructor since lambda types are not default constructible.

而且我不确定是否可以在 godbolt 上对给定的示例进行操作。

我认为你做不到。使用标准容器,您将不得不向构造函数提供实际实例。但是,MultiIndex 负担不起:

docs

As explained in the index concepts section, indices do not have public constructors or destructors. Assignment, on the other hand, is provided. Upon construction, max_load_factor() is 1.0.

漏洞?

您或许可以使用本地定义的 class:

auto const hash_f = [](int const& n) { return std::hash<int>()(n); };
struct HashType : decltype(hash_f) {};

using AnimalsMultiIndex = multi_index_container<
    Animal, indexed_by<hashed_non_unique<
                tag<animal_legs>, member<Animal, LegsType, &Animal::legs>,
                HashType>>>;

AnimalsMultiIndex animals;

哪个有效:c++20 required

#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/tag.hpp>
#include <boost/multi_index_container.hpp>
#include <iostream>
#include <string>

using namespace boost::multi_index;
using LegsType = int;

struct Animal {
    std::string name;
    LegsType legs;
};

// tags
struct animal_legs {};

int main() {
    // using lambda doesn't work for hashing
    auto const hash_f = [](int const& n) { return std::hash<int>()(n); };
    struct HashType : decltype(hash_f) {};

    using AnimalsMultiIndex = multi_index_container<
        Animal, indexed_by<hashed_non_unique<
                    tag<animal_legs>, member<Animal, LegsType, &Animal::legs>,
                    HashType>>>;

    AnimalsMultiIndex animals;

    animals.insert({ "cat", 4 });

    auto const& legs_index = animals.get<animal_legs>();
    int num_of_legs = 4;
    std::cout << "Number of animals that have " << num_of_legs
              << " legs is: " << legs_index.count(num_of_legs) << '\n';
}

版画

Number of animals that have 4 legs is: 1

从 C++20 开始,是的,您可以:https://godbolt.org/z/fTbzPP(注意 f 声明为 auto const hash_f,没有 &)。

至于@sehe 声称 multi_index_containers 不能在构造时传递散列对象(或其他干预函数对象)的实例,这种说法是不正确的:它们可以,尽管接口有点复杂:

Live Coliru Demo

#include <boost/multi_index_container.hpp>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/identity.hpp>
#include <functional>

struct non_default_ctble_hash
{
  non_default_ctble_hash(std::size_t n):n{n}{}
  
  template<typename T>
  std::size_t operator()(const T& x){return std::hash<T>{}(x)*n;}

  std::size_t n;
};

using namespace boost::multi_index;
using container=multi_index_container<
  int,
  indexed_by<
    hashed_unique<identity<int>,non_default_ctble_hash>
  >
>;

int main()
{
  container::ctor_args_list cal{
    {0,identity<int>{},non_default_ctble_hash{666},std::equal_to<int>{}}
  };
  
  container c(cal);
}