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

dal*_*cai 0 c++ unordered-map variant

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

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

using VariantType = std::variant<int, std::string, unsigned int>;
std::unordered_map<VariantType, int, $some_hash_function$> m;
Run Code Online (Sandbox Code Playgroud)

如何实现 $some_hash_function$?

Jer*_*iah 5

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

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

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

如果启用了每个专业化,则启用专业化std::hash<std::variant<Types...>>(请参阅 std::hash)std::hash<std::remove_const_t<Types>>...,否则禁用。

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

错误:静态断言失败:哈希函数必须可以使用键类型的参数调用

回到你的问题:

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

#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];
}
Run Code Online (Sandbox Code Playgroud)

你得到这个输出:

Program returned: 0
Program stdout
3
Run Code Online (Sandbox Code Playgroud)

当并非所有变体类型都具有哈希函数时:

#include <variant>
#include <unordered_map>
#include <string>
#include <iostream>
class UnhashedClass {};
using VariantType = std::variant<UnhashedClass, int, std::string>;
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];
}
Run Code Online (Sandbox Code Playgroud)

你得到这个输出:

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
...
Run Code Online (Sandbox Code Playgroud)

你可以在这里自己尝试一下:

https://godbolt.org/z/bnzcE9