Но речь не об этом.
Как написано в cppreference, если ключи равны, то и хеши от них равны.
```
Given the following values:
h, an object of type std::hash<Key>.k1 and k2, objects of type Key.All following requirements are satisfied:
- If
k1 == k2 is true, h(k1) == h(k2) is also true.- Unless
std::hash<Key> is a program-defined specialization, h(k1) will never throw an exception.```
Иногда срабатывает даже если это объекты разных типов
const auto x1 = 42;
const auto x2 = 42u;
__builtin_printf("%b\n\n", x1 == x2);
__builtin_printf("%#08zx\n%#08zx\n",
std::hash<int>{}(x1),
std::hash<unsigned>{}(x2));
1
0x00002a
0x00002a
А вот если вы упакуете те же типы в обертку типа json:
const auto j1 = json{x1};
const auto j2 = json{x2};
__builtin_printf("%b\n\n", j1 == j2);
__builtin_printf("%#08zx\n%#08zx\n",
std::hash<json>{}(j1),
std::hash<json>{}(j2));
Тут уже как повезет. Конкретно для этой библиотеке не сраслось:
1
0x286fec1b50
0x286fec1b91
Потому что там есть своя специализация. И с ней это правило для hash не работает.
namespace std // NOLINT(cert-dcl58-cpp)
{
/// @brief hash value for JSON objects
/// @sa https://json.nlohmann.me/api/basic_json/std_hash/
NLOHMANN_BASIC_JSON_TPL_DECLARATION
struct hash<nlohmann::NLOHMANN_BASIC_JSON_TPL> // NOLINT(cert-dcl58-cpp)
{
std::size_t operator()(const nlohmann::NLOHMANN_BASIC_JSON_TPL& j) const
{
return nlohmann::detail::hash(j);
}
};
А потому эту штуку очень весело бывает использовать в hash-мапах, когда два одинаковых объекта могут стать разными ключами.
Сохраняем бдительность!!!!