如何使用变体作为unordered_map中的键?

问题描述

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

例如,我想使以下代码起作用。

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

如何实现$ some_hash_function $?

解决方法

已经有一个变体的哈希模板专门化:

http://en.cppreference.com/w/cpp/utility/variant/hash

唯一的条件是,变体中的每个类型都必须具有哈希函数:

如果std::hash<std::variant<Types...>>中的每个特殊化都已启用,则特殊化std::hash<std::remove_const_t<Types>>...被启用(请参阅std :: hash)。否则,则被禁用。

但是所有变量类型都有默认哈希,因此,对于变量类型,由于标准哈希有效,因此无需第三个参数即可进行编译。但是,如果您的变体中的某个类型没有哈希函数(或==运算符),那么它将无法编译,并显示以下错误:

错误:静态声明失败:哈希函数必须可调用且键类型为参数

回到您的问题:

当变体类型具有哈希函数时:

#include <variant>
#include <unordered_map>
#include <string>
#include <iostream>
using VariantType = std::variant<int,std::string,unsigned int>;
std::unordered_map<VariantType,int> m =
{
 {1,1},{2u,2},{std::string("string"),3}
};
int main()
{
    VariantType v = std::string{"string"};
    std::cout << m[v];
}

您将获得以下输出:

Program returned: 0
Program stdout
3

当不是所有的变体类型都具有哈希函数时:

#include <variant>
#include <unordered_map>
#include <string>
#include <iostream>
class UnhashedClass {};
using VariantType = std::variant<UnhashedClass,int,std::string>;
std::unordered_map<VariantType,3}
};
int main()
{
    VariantType v = std::string{"string"};
    std::cout << m[v];
}

您将获得以下输出:

Could not execute the program
Compiler returned: 1
Compiler stderr
...
error: static assertion failed: hash function must be invocable with an argument of key type
...

您可以在这里自己尝试:

https://godbolt.org/z/bnzcE9