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

问题描述

如何使用变体向量作为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 $?

解决方法

我喜欢一个好主意...

除了“我想知道是否可以编译并运行”示例之外,我不知道如何或为什么将类似的东西用于这种情况。

#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,Hasher> m;
    auto one = VecVariantType { 1,"one",1u };
    auto two = VecVariantType { 2,"two",2u };
    auto three = VecVariantType { 3,"three",3u };
    auto nnn = VecVariantType { 1,1u,2,2u,3,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