【问题标题】:How to use a vector variants as key in unordered_map?如何使用向量变体作为 unordered_map 中的键?
【发布时间】:2020-08-27 16:25:42
【问题描述】:

如何在 unordered_map 中使用变体向量作为键?

例如,我想让下面的代码工作。

using VariantType = std::variant<int, std::string, unsigned int>;
using VecVariantType = std::vector<VariantType>;
std::unordered_map<VecVariantType, int, $some_hash_function$> m;

如何实现 $some_hash_function$?

【问题讨论】:

  • 建议:If a question不清楚,或者不是minimal reproducible example,不加修改再发帖不是个好主意。
  • 您确定需要这样的地图吗?这没有任何意义。将变体向量映射到 int 的示例是什么?
  • 这与您昨天问的问题基本相同吗? stackoverflow.com/questions/63607075/…
  • @RetiredNinja 昨天的问题基本上有误。代码示例省略了vector,并且在更正之前没有vector 回答了问题。由于答案是正确的,我回复了这个问题,并建议用vector再次提问。
  • @Mansoor 同上。这两种情况下的问题都缺少 MRE,但是由于提问者知道这一点并且知道他们没有什么行不通,所以这应该足够清楚。是的,它可能仍然是一个 XY 问题,使用 vectorvariant 作为映射键很可能是一个糟糕的设计决策,但选择更简单,但问题的目标很明确。至少对我来说很清楚。好主意,可能不会。

标签: c++ hash unordered-map variant


【解决方案1】:

我喜欢一个好主意……

除了“我想知道我是否可以编译和运行”示例之外,我不知道您如何或为什么会使用这样的东西。

#include <iostream>
#include <vector>
#include <unordered_map>
#include <variant>

using VariantType = std::variant<int, std::string, unsigned int>;
using VecVariantType = std::vector<VariantType>;

struct Hasher
{
    size_t operator()(const VecVariantType &v) const
    {
        size_t hash = 0;
        for (auto &val : v)
        {
            hash ^= std::hash<VariantType>()(val);
        }
        return hash;
    }
};

std::ostream& operator<<(std::ostream& out, std::pair<const VecVariantType, int> &p)
{
    out << "key: { ";
    bool needs_comma = false;
    for (auto &var : p.first)
    {
        if (needs_comma)
        {
            out << ", ";
        }
        if (std::holds_alternative<int>(var))
        {
            out << "int: " << std::get<int>(var);
            needs_comma = true;
        }
        if (std::holds_alternative<std::string>(var))
        {
            out << "string: " << std::get<std::string>(var);
            needs_comma = true;
        }
        if (std::holds_alternative<unsigned int>(var))
        {
            out << "uint: " << std::get<unsigned int>(var);
            needs_comma = true;
        }
    }
    out << " }, value: " << p.second;
    return out;
}

void lookup(const VecVariantType &var, std::unordered_map<VecVariantType, int, Hasher> &m)
{
    std::cout << "Lookup ";
    auto it = m.find(var);
    if (it != m.end())
    {
        std::cout << "success - " << *it << "\n";
    }
    else
    {
        std::cout << "failure\n";
    }
}

int main()
{
    std::unordered_map<VecVariantType, int, Hasher> m;
    auto one = VecVariantType { 1, "one", 1u };
    auto two = VecVariantType { 2, "two", 2u };
    auto three = VecVariantType { 3, "three", 3u };
    auto nnn = VecVariantType { 1, "one", 1u, 2, "two", 2u, 3, "three", 3u };
    m.emplace(one, 1);
    m.emplace(two, 2);
    m.emplace(three, 3);
    m.emplace(nnn, 999);

    std::cout << "Enumerating:\n";
    for (auto& item : m)
    {
        std::cout << "    " << item << "\n";
    }

    lookup(one, m);
    lookup(two, m);
    lookup(three, m);
    lookup(nnn, m);
}

https://repl.it/repls/AmazingCrushingOpen64

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-05-27
    • 2023-03-14
    • 1970-01-01
    • 1970-01-01
    • 2018-07-09
    • 2019-11-17
    • 2012-08-30
    • 1970-01-01
    相关资源
    最近更新 更多