There is already a hash template specialization for variant:
http://en.cppreference.com/w/cpp/utility/variant/hash
The only condition is that every type in the variant must have a hash function:
The specialization std::hash<std::variant<Types...>>
is enabled (see std::hash) if every specialization in std::hash<std::remove_const_t<Types>>...
is enabled, and is disabled otherwise.
But all your variant types have default hashes so, for your variant types, it compiles without the third parameter because the standard hash works. However, if you had a type in your variant that did not have a hash function (or an == operator) then it would fail to compile with this error:
error: static assertion failed: hash function must be invocable with an argument of key type
So back to your question:
When the variant types have hash functions:
#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];
}
You get this output:
Program returned: 0
Program stdout
3
And when not all the variant types have hash functions:
#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];
}
You get this output:
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
...
You can try it yourself here:
https://godbolt.org/z/bnzcE9