hash_function_defaults_test.cc (19335B)
1 // Copyright 2018 The Abseil Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #include "absl/container/internal/hash_function_defaults.h" 16 17 #include <cstddef> 18 #include <functional> 19 #include <type_traits> 20 #include <utility> 21 22 #include "gtest/gtest.h" 23 #include "absl/container/flat_hash_map.h" 24 #include "absl/container/flat_hash_set.h" 25 #include "absl/hash/hash.h" 26 #include "absl/random/random.h" 27 #include "absl/strings/cord.h" 28 #include "absl/strings/cord_test_helpers.h" 29 #include "absl/strings/string_view.h" 30 31 #ifdef ABSL_HAVE_STD_STRING_VIEW 32 #include <string_view> 33 #endif 34 35 namespace absl { 36 ABSL_NAMESPACE_BEGIN 37 namespace container_internal { 38 namespace { 39 40 using ::testing::Types; 41 42 TEST(Eq, Int32) { 43 hash_default_eq<int32_t> eq; 44 EXPECT_TRUE(eq(1, 1u)); 45 EXPECT_TRUE(eq(1, char{1})); 46 EXPECT_TRUE(eq(1, true)); 47 EXPECT_TRUE(eq(1, double{1.1})); 48 EXPECT_FALSE(eq(1, char{2})); 49 EXPECT_FALSE(eq(1, 2u)); 50 EXPECT_FALSE(eq(1, false)); 51 EXPECT_FALSE(eq(1, 2.)); 52 } 53 54 TEST(Hash, Int32) { 55 hash_default_hash<int32_t> hash; 56 auto h = hash(1); 57 EXPECT_EQ(h, hash(1u)); 58 EXPECT_EQ(h, hash(char{1})); 59 EXPECT_EQ(h, hash(true)); 60 EXPECT_EQ(h, hash(double{1.1})); 61 EXPECT_NE(h, hash(2u)); 62 EXPECT_NE(h, hash(char{2})); 63 EXPECT_NE(h, hash(false)); 64 EXPECT_NE(h, hash(2.)); 65 } 66 67 enum class MyEnum { A, B, C, D }; 68 69 TEST(Eq, Enum) { 70 hash_default_eq<MyEnum> eq; 71 EXPECT_TRUE(eq(MyEnum::A, MyEnum::A)); 72 EXPECT_FALSE(eq(MyEnum::A, MyEnum::B)); 73 } 74 75 TEST(Hash, Enum) { 76 hash_default_hash<MyEnum> hash; 77 78 for (MyEnum e : {MyEnum::A, MyEnum::B, MyEnum::C}) { 79 auto h = hash(e); 80 EXPECT_EQ(h, hash_default_hash<int>{}(static_cast<int>(e))); 81 EXPECT_NE(h, hash(MyEnum::D)); 82 } 83 } 84 85 using StringTypes = ::testing::Types<std::string, absl::string_view>; 86 87 template <class T> 88 struct EqString : ::testing::Test { 89 hash_default_eq<T> key_eq; 90 }; 91 92 TYPED_TEST_SUITE(EqString, StringTypes); 93 94 template <class T> 95 struct HashString : ::testing::Test { 96 hash_default_hash<T> hasher; 97 }; 98 99 TYPED_TEST_SUITE(HashString, StringTypes); 100 101 TYPED_TEST(EqString, Works) { 102 auto eq = this->key_eq; 103 EXPECT_TRUE(eq("a", "a")); 104 EXPECT_TRUE(eq("a", absl::string_view("a"))); 105 EXPECT_TRUE(eq("a", std::string("a"))); 106 EXPECT_FALSE(eq("a", "b")); 107 EXPECT_FALSE(eq("a", absl::string_view("b"))); 108 EXPECT_FALSE(eq("a", std::string("b"))); 109 } 110 111 TYPED_TEST(HashString, Works) { 112 auto hash = this->hasher; 113 auto h = hash("a"); 114 EXPECT_EQ(h, hash(absl::string_view("a"))); 115 EXPECT_EQ(h, hash(std::string("a"))); 116 EXPECT_NE(h, hash(absl::string_view("b"))); 117 EXPECT_NE(h, hash(std::string("b"))); 118 } 119 120 TEST(BasicStringViewTest, WStringEqWorks) { 121 #ifndef ABSL_HAVE_STD_STRING_VIEW 122 GTEST_SKIP(); 123 #else 124 hash_default_eq<std::wstring> eq; 125 EXPECT_TRUE(eq(L"a", L"a")); 126 EXPECT_TRUE(eq(L"a", std::wstring_view(L"a"))); 127 EXPECT_TRUE(eq(L"a", std::wstring(L"a"))); 128 EXPECT_FALSE(eq(L"a", L"b")); 129 EXPECT_FALSE(eq(L"a", std::wstring_view(L"b"))); 130 EXPECT_FALSE(eq(L"a", std::wstring(L"b"))); 131 #endif 132 } 133 134 TEST(BasicStringViewTest, WStringViewEqWorks) { 135 #ifndef ABSL_HAVE_STD_STRING_VIEW 136 GTEST_SKIP(); 137 #else 138 hash_default_eq<std::wstring_view> eq; 139 EXPECT_TRUE(eq(L"a", L"a")); 140 EXPECT_TRUE(eq(L"a", std::wstring_view(L"a"))); 141 EXPECT_TRUE(eq(L"a", std::wstring(L"a"))); 142 EXPECT_FALSE(eq(L"a", L"b")); 143 EXPECT_FALSE(eq(L"a", std::wstring_view(L"b"))); 144 EXPECT_FALSE(eq(L"a", std::wstring(L"b"))); 145 #endif 146 } 147 148 TEST(BasicStringViewTest, U16StringEqWorks) { 149 #ifndef ABSL_HAVE_STD_STRING_VIEW 150 GTEST_SKIP(); 151 #else 152 hash_default_eq<std::u16string> eq; 153 EXPECT_TRUE(eq(u"a", u"a")); 154 EXPECT_TRUE(eq(u"a", std::u16string_view(u"a"))); 155 EXPECT_TRUE(eq(u"a", std::u16string(u"a"))); 156 EXPECT_FALSE(eq(u"a", u"b")); 157 EXPECT_FALSE(eq(u"a", std::u16string_view(u"b"))); 158 EXPECT_FALSE(eq(u"a", std::u16string(u"b"))); 159 #endif 160 } 161 162 TEST(BasicStringViewTest, U16StringViewEqWorks) { 163 #ifndef ABSL_HAVE_STD_STRING_VIEW 164 GTEST_SKIP(); 165 #else 166 hash_default_eq<std::u16string_view> eq; 167 EXPECT_TRUE(eq(u"a", u"a")); 168 EXPECT_TRUE(eq(u"a", std::u16string_view(u"a"))); 169 EXPECT_TRUE(eq(u"a", std::u16string(u"a"))); 170 EXPECT_FALSE(eq(u"a", u"b")); 171 EXPECT_FALSE(eq(u"a", std::u16string_view(u"b"))); 172 EXPECT_FALSE(eq(u"a", std::u16string(u"b"))); 173 #endif 174 } 175 176 TEST(BasicStringViewTest, U32StringEqWorks) { 177 #ifndef ABSL_HAVE_STD_STRING_VIEW 178 GTEST_SKIP(); 179 #else 180 hash_default_eq<std::u32string> eq; 181 EXPECT_TRUE(eq(U"a", U"a")); 182 EXPECT_TRUE(eq(U"a", std::u32string_view(U"a"))); 183 EXPECT_TRUE(eq(U"a", std::u32string(U"a"))); 184 EXPECT_FALSE(eq(U"a", U"b")); 185 EXPECT_FALSE(eq(U"a", std::u32string_view(U"b"))); 186 EXPECT_FALSE(eq(U"a", std::u32string(U"b"))); 187 #endif 188 } 189 190 TEST(BasicStringViewTest, U32StringViewEqWorks) { 191 #ifndef ABSL_HAVE_STD_STRING_VIEW 192 GTEST_SKIP(); 193 #else 194 hash_default_eq<std::u32string_view> eq; 195 EXPECT_TRUE(eq(U"a", U"a")); 196 EXPECT_TRUE(eq(U"a", std::u32string_view(U"a"))); 197 EXPECT_TRUE(eq(U"a", std::u32string(U"a"))); 198 EXPECT_FALSE(eq(U"a", U"b")); 199 EXPECT_FALSE(eq(U"a", std::u32string_view(U"b"))); 200 EXPECT_FALSE(eq(U"a", std::u32string(U"b"))); 201 #endif 202 } 203 204 TEST(BasicStringViewTest, WStringHashWorks) { 205 #ifndef ABSL_HAVE_STD_STRING_VIEW 206 GTEST_SKIP(); 207 #else 208 hash_default_hash<std::wstring> hash; 209 auto h = hash(L"a"); 210 EXPECT_EQ(h, hash(std::wstring_view(L"a"))); 211 EXPECT_EQ(h, hash(std::wstring(L"a"))); 212 EXPECT_NE(h, hash(std::wstring_view(L"b"))); 213 EXPECT_NE(h, hash(std::wstring(L"b"))); 214 #endif 215 } 216 217 TEST(BasicStringViewTest, WStringViewHashWorks) { 218 #ifndef ABSL_HAVE_STD_STRING_VIEW 219 GTEST_SKIP(); 220 #else 221 hash_default_hash<std::wstring_view> hash; 222 auto h = hash(L"a"); 223 EXPECT_EQ(h, hash(std::wstring_view(L"a"))); 224 EXPECT_EQ(h, hash(std::wstring(L"a"))); 225 EXPECT_NE(h, hash(std::wstring_view(L"b"))); 226 EXPECT_NE(h, hash(std::wstring(L"b"))); 227 #endif 228 } 229 230 TEST(BasicStringViewTest, U16StringHashWorks) { 231 #ifndef ABSL_HAVE_STD_STRING_VIEW 232 GTEST_SKIP(); 233 #else 234 hash_default_hash<std::u16string> hash; 235 auto h = hash(u"a"); 236 EXPECT_EQ(h, hash(std::u16string_view(u"a"))); 237 EXPECT_EQ(h, hash(std::u16string(u"a"))); 238 EXPECT_NE(h, hash(std::u16string_view(u"b"))); 239 EXPECT_NE(h, hash(std::u16string(u"b"))); 240 #endif 241 } 242 243 TEST(BasicStringViewTest, U16StringViewHashWorks) { 244 #ifndef ABSL_HAVE_STD_STRING_VIEW 245 GTEST_SKIP(); 246 #else 247 hash_default_hash<std::u16string_view> hash; 248 auto h = hash(u"a"); 249 EXPECT_EQ(h, hash(std::u16string_view(u"a"))); 250 EXPECT_EQ(h, hash(std::u16string(u"a"))); 251 EXPECT_NE(h, hash(std::u16string_view(u"b"))); 252 EXPECT_NE(h, hash(std::u16string(u"b"))); 253 #endif 254 } 255 256 TEST(BasicStringViewTest, U32StringHashWorks) { 257 #ifndef ABSL_HAVE_STD_STRING_VIEW 258 GTEST_SKIP(); 259 #else 260 hash_default_hash<std::u32string> hash; 261 auto h = hash(U"a"); 262 EXPECT_EQ(h, hash(std::u32string_view(U"a"))); 263 EXPECT_EQ(h, hash(std::u32string(U"a"))); 264 EXPECT_NE(h, hash(std::u32string_view(U"b"))); 265 EXPECT_NE(h, hash(std::u32string(U"b"))); 266 #endif 267 } 268 269 TEST(BasicStringViewTest, U32StringViewHashWorks) { 270 #ifndef ABSL_HAVE_STD_STRING_VIEW 271 GTEST_SKIP(); 272 #else 273 hash_default_hash<std::u32string_view> hash; 274 auto h = hash(U"a"); 275 EXPECT_EQ(h, hash(std::u32string_view(U"a"))); 276 EXPECT_EQ(h, hash(std::u32string(U"a"))); 277 EXPECT_NE(h, hash(std::u32string_view(U"b"))); 278 EXPECT_NE(h, hash(std::u32string(U"b"))); 279 #endif 280 } 281 282 struct NoDeleter { 283 template <class T> 284 void operator()(const T* ptr) const {} 285 }; 286 287 using PointerTypes = 288 ::testing::Types<const int*, int*, std::unique_ptr<const int>, 289 std::unique_ptr<const int, NoDeleter>, 290 std::unique_ptr<int>, std::unique_ptr<int, NoDeleter>, 291 std::shared_ptr<const int>, std::shared_ptr<int>>; 292 293 template <class T> 294 struct EqPointer : ::testing::Test { 295 hash_default_eq<T> key_eq; 296 }; 297 298 TYPED_TEST_SUITE(EqPointer, PointerTypes); 299 300 template <class T> 301 struct HashPointer : ::testing::Test { 302 hash_default_hash<T> hasher; 303 }; 304 305 TYPED_TEST_SUITE(HashPointer, PointerTypes); 306 307 TYPED_TEST(EqPointer, Works) { 308 int dummy; 309 auto eq = this->key_eq; 310 auto sptr = std::make_shared<int>(); 311 std::shared_ptr<const int> csptr = sptr; 312 int* ptr = sptr.get(); 313 const int* cptr = ptr; 314 std::unique_ptr<int, NoDeleter> uptr(ptr); 315 std::unique_ptr<const int, NoDeleter> cuptr(ptr); 316 317 EXPECT_TRUE(eq(ptr, cptr)); 318 EXPECT_TRUE(eq(ptr, sptr)); 319 EXPECT_TRUE(eq(ptr, uptr)); 320 EXPECT_TRUE(eq(ptr, csptr)); 321 EXPECT_TRUE(eq(ptr, cuptr)); 322 EXPECT_FALSE(eq(&dummy, cptr)); 323 EXPECT_FALSE(eq(&dummy, sptr)); 324 EXPECT_FALSE(eq(&dummy, uptr)); 325 EXPECT_FALSE(eq(&dummy, csptr)); 326 EXPECT_FALSE(eq(&dummy, cuptr)); 327 } 328 329 TEST(Hash, DerivedAndBase) { 330 struct Base {}; 331 struct Derived : Base {}; 332 333 hash_default_hash<Base*> hasher; 334 335 Base base; 336 Derived derived; 337 EXPECT_NE(hasher(&base), hasher(&derived)); 338 EXPECT_EQ(hasher(static_cast<Base*>(&derived)), hasher(&derived)); 339 340 auto dp = std::make_shared<Derived>(); 341 EXPECT_EQ(hasher(static_cast<Base*>(dp.get())), hasher(dp)); 342 } 343 344 TEST(Hash, FunctionPointer) { 345 using Func = int (*)(); 346 hash_default_hash<Func> hasher; 347 hash_default_eq<Func> eq; 348 349 Func p1 = [] { return 1; }, p2 = [] { return 2; }; 350 EXPECT_EQ(hasher(p1), hasher(p1)); 351 EXPECT_TRUE(eq(p1, p1)); 352 353 EXPECT_NE(hasher(p1), hasher(p2)); 354 EXPECT_FALSE(eq(p1, p2)); 355 } 356 357 TYPED_TEST(HashPointer, Works) { 358 int dummy; 359 auto hash = this->hasher; 360 auto sptr = std::make_shared<int>(); 361 std::shared_ptr<const int> csptr = sptr; 362 int* ptr = sptr.get(); 363 const int* cptr = ptr; 364 std::unique_ptr<int, NoDeleter> uptr(ptr); 365 std::unique_ptr<const int, NoDeleter> cuptr(ptr); 366 367 EXPECT_EQ(hash(ptr), hash(cptr)); 368 EXPECT_EQ(hash(ptr), hash(sptr)); 369 EXPECT_EQ(hash(ptr), hash(uptr)); 370 EXPECT_EQ(hash(ptr), hash(csptr)); 371 EXPECT_EQ(hash(ptr), hash(cuptr)); 372 EXPECT_NE(hash(&dummy), hash(cptr)); 373 EXPECT_NE(hash(&dummy), hash(sptr)); 374 EXPECT_NE(hash(&dummy), hash(uptr)); 375 EXPECT_NE(hash(&dummy), hash(csptr)); 376 EXPECT_NE(hash(&dummy), hash(cuptr)); 377 } 378 379 TEST(EqCord, Works) { 380 hash_default_eq<absl::Cord> eq; 381 const absl::string_view a_string_view = "a"; 382 const absl::Cord a_cord(a_string_view); 383 const absl::string_view b_string_view = "b"; 384 const absl::Cord b_cord(b_string_view); 385 386 EXPECT_TRUE(eq(a_cord, a_cord)); 387 EXPECT_TRUE(eq(a_cord, a_string_view)); 388 EXPECT_TRUE(eq(a_string_view, a_cord)); 389 EXPECT_FALSE(eq(a_cord, b_cord)); 390 EXPECT_FALSE(eq(a_cord, b_string_view)); 391 EXPECT_FALSE(eq(b_string_view, a_cord)); 392 } 393 394 TEST(HashCord, Works) { 395 hash_default_hash<absl::Cord> hash; 396 const absl::string_view a_string_view = "a"; 397 const absl::Cord a_cord(a_string_view); 398 const absl::string_view b_string_view = "b"; 399 const absl::Cord b_cord(b_string_view); 400 401 EXPECT_EQ(hash(a_cord), hash(a_cord)); 402 EXPECT_EQ(hash(b_cord), hash(b_cord)); 403 EXPECT_EQ(hash(a_string_view), hash(a_cord)); 404 EXPECT_EQ(hash(b_string_view), hash(b_cord)); 405 EXPECT_EQ(hash(absl::Cord("")), hash("")); 406 EXPECT_EQ(hash(absl::Cord()), hash(absl::string_view())); 407 408 EXPECT_NE(hash(a_cord), hash(b_cord)); 409 EXPECT_NE(hash(a_cord), hash(b_string_view)); 410 EXPECT_NE(hash(a_string_view), hash(b_cord)); 411 EXPECT_NE(hash(a_string_view), hash(b_string_view)); 412 } 413 414 void NoOpReleaser(absl::string_view data, void* arg) {} 415 416 TEST(HashCord, FragmentedCordWorks) { 417 hash_default_hash<absl::Cord> hash; 418 absl::Cord c = absl::MakeFragmentedCord({"a", "b", "c"}); 419 EXPECT_FALSE(c.TryFlat().has_value()); 420 EXPECT_EQ(hash(c), hash("abc")); 421 } 422 423 TEST(HashCord, FragmentedLongCordWorks) { 424 hash_default_hash<absl::Cord> hash; 425 // Crete some large strings which do not fit on the stack. 426 std::string a(65536, 'a'); 427 std::string b(65536, 'b'); 428 absl::Cord c = absl::MakeFragmentedCord({a, b}); 429 EXPECT_FALSE(c.TryFlat().has_value()); 430 EXPECT_EQ(hash(c), hash(a + b)); 431 } 432 433 TEST(HashCord, RandomCord) { 434 hash_default_hash<absl::Cord> hash; 435 auto bitgen = absl::BitGen(); 436 for (int i = 0; i < 1000; ++i) { 437 const int number_of_segments = absl::Uniform(bitgen, 0, 10); 438 std::vector<std::string> pieces; 439 for (size_t s = 0; s < number_of_segments; ++s) { 440 std::string str; 441 str.resize(absl::Uniform(bitgen, 0, 4096)); 442 // MSVC needed the explicit return type in the lambda. 443 std::generate(str.begin(), str.end(), [&]() -> char { 444 return static_cast<char>(absl::Uniform<unsigned char>(bitgen)); 445 }); 446 pieces.push_back(str); 447 } 448 absl::Cord c = absl::MakeFragmentedCord(pieces); 449 EXPECT_EQ(hash(c), hash(std::string(c))); 450 } 451 } 452 453 // Cartesian product of (std::string, absl::string_view) 454 // with (std::string, absl::string_view, const char*, absl::Cord). 455 using StringTypesCartesianProduct = Types< 456 // clang-format off 457 std::pair<absl::Cord, std::string>, 458 std::pair<absl::Cord, absl::string_view>, 459 std::pair<absl::Cord, absl::Cord>, 460 std::pair<absl::Cord, const char*>, 461 462 std::pair<std::string, absl::Cord>, 463 std::pair<absl::string_view, absl::Cord>, 464 465 std::pair<absl::string_view, std::string>, 466 std::pair<absl::string_view, absl::string_view>, 467 std::pair<absl::string_view, const char*>>; 468 // clang-format on 469 470 constexpr char kFirstString[] = "abc123"; 471 constexpr char kSecondString[] = "ijk456"; 472 473 template <typename T> 474 struct StringLikeTest : public ::testing::Test { 475 typename T::first_type a1{kFirstString}; 476 typename T::second_type b1{kFirstString}; 477 typename T::first_type a2{kSecondString}; 478 typename T::second_type b2{kSecondString}; 479 hash_default_eq<typename T::first_type> eq; 480 hash_default_hash<typename T::first_type> hash; 481 }; 482 483 TYPED_TEST_SUITE(StringLikeTest, StringTypesCartesianProduct); 484 485 TYPED_TEST(StringLikeTest, Eq) { 486 EXPECT_TRUE(this->eq(this->a1, this->b1)); 487 EXPECT_TRUE(this->eq(this->b1, this->a1)); 488 } 489 490 TYPED_TEST(StringLikeTest, NotEq) { 491 EXPECT_FALSE(this->eq(this->a1, this->b2)); 492 EXPECT_FALSE(this->eq(this->b2, this->a1)); 493 } 494 495 TYPED_TEST(StringLikeTest, HashEq) { 496 EXPECT_EQ(this->hash(this->a1), this->hash(this->b1)); 497 EXPECT_EQ(this->hash(this->a2), this->hash(this->b2)); 498 // It would be a poor hash function which collides on these strings. 499 EXPECT_NE(this->hash(this->a1), this->hash(this->b2)); 500 } 501 502 struct TypeWithAbslContainerHash { 503 struct absl_container_hash { 504 using is_transparent = void; 505 506 size_t operator()(const TypeWithAbslContainerHash& foo) const { 507 return absl::HashOf(foo.value); 508 } 509 510 // Extra overload to test that heterogeneity works for this hasher. 511 size_t operator()(int value) const { return absl::HashOf(value); } 512 }; 513 514 friend bool operator==(const TypeWithAbslContainerHash& lhs, 515 const TypeWithAbslContainerHash& rhs) { 516 return lhs.value == rhs.value; 517 } 518 519 friend bool operator==(const TypeWithAbslContainerHash& lhs, int rhs) { 520 return lhs.value == rhs; 521 } 522 523 int value; 524 int noise; 525 }; 526 527 struct TypeWithAbslContainerHashAndEq { 528 struct absl_container_hash { 529 using is_transparent = void; 530 531 size_t operator()(const TypeWithAbslContainerHashAndEq& foo) const { 532 return absl::HashOf(foo.value); 533 } 534 535 // Extra overload to test that heterogeneity works for this hasher. 536 size_t operator()(int value) const { return absl::HashOf(value); } 537 }; 538 539 struct absl_container_eq { 540 using is_transparent = void; 541 542 bool operator()(const TypeWithAbslContainerHashAndEq& lhs, 543 const TypeWithAbslContainerHashAndEq& rhs) const { 544 return lhs.value == rhs.value; 545 } 546 547 // Extra overload to test that heterogeneity works for this eq. 548 bool operator()(const TypeWithAbslContainerHashAndEq& lhs, int rhs) const { 549 return lhs.value == rhs; 550 } 551 }; 552 553 template <typename T> 554 bool operator==(T&& other) const = delete; 555 556 int value; 557 int noise; 558 }; 559 560 using AbslContainerHashTypes = 561 Types<TypeWithAbslContainerHash, TypeWithAbslContainerHashAndEq>; 562 563 template <typename T> 564 using AbslContainerHashTest = ::testing::Test; 565 566 TYPED_TEST_SUITE(AbslContainerHashTest, AbslContainerHashTypes); 567 568 TYPED_TEST(AbslContainerHashTest, HasherWorks) { 569 hash_default_hash<TypeParam> hasher; 570 571 TypeParam foo1{/*value=*/1, /*noise=*/100}; 572 TypeParam foo1_copy{/*value=*/1, /*noise=*/20}; 573 TypeParam foo2{/*value=*/2, /*noise=*/100}; 574 575 EXPECT_EQ(hasher(foo1), absl::HashOf(1)); 576 EXPECT_EQ(hasher(foo2), absl::HashOf(2)); 577 EXPECT_EQ(hasher(foo1), hasher(foo1_copy)); 578 579 // Heterogeneity works. 580 EXPECT_EQ(hasher(foo1), hasher(1)); 581 EXPECT_EQ(hasher(foo2), hasher(2)); 582 } 583 584 TYPED_TEST(AbslContainerHashTest, EqWorks) { 585 hash_default_eq<TypeParam> eq; 586 587 TypeParam foo1{/*value=*/1, /*noise=*/100}; 588 TypeParam foo1_copy{/*value=*/1, /*noise=*/20}; 589 TypeParam foo2{/*value=*/2, /*noise=*/100}; 590 591 EXPECT_TRUE(eq(foo1, foo1_copy)); 592 EXPECT_FALSE(eq(foo1, foo2)); 593 594 // Heterogeneity works. 595 EXPECT_TRUE(eq(foo1, 1)); 596 EXPECT_FALSE(eq(foo1, 2)); 597 } 598 599 TYPED_TEST(AbslContainerHashTest, HeterogeneityInMapWorks) { 600 absl::flat_hash_map<TypeParam, int> map; 601 602 TypeParam foo1{/*value=*/1, /*noise=*/100}; 603 TypeParam foo1_copy{/*value=*/1, /*noise=*/20}; 604 TypeParam foo2{/*value=*/2, /*noise=*/100}; 605 TypeParam foo3{/*value=*/3, /*noise=*/100}; 606 607 map[foo1] = 1; 608 map[foo2] = 2; 609 610 EXPECT_TRUE(map.contains(foo1_copy)); 611 EXPECT_EQ(map.at(foo1_copy), 1); 612 EXPECT_TRUE(map.contains(1)); 613 EXPECT_EQ(map.at(1), 1); 614 EXPECT_TRUE(map.contains(2)); 615 EXPECT_EQ(map.at(2), 2); 616 EXPECT_FALSE(map.contains(foo3)); 617 EXPECT_FALSE(map.contains(3)); 618 } 619 620 TYPED_TEST(AbslContainerHashTest, HeterogeneityInSetWorks) { 621 absl::flat_hash_set<TypeParam> set; 622 623 TypeParam foo1{/*value=*/1, /*noise=*/100}; 624 TypeParam foo1_copy{/*value=*/1, /*noise=*/20}; 625 TypeParam foo2{/*value=*/2, /*noise=*/100}; 626 627 set.insert(foo1); 628 629 EXPECT_TRUE(set.contains(foo1_copy)); 630 EXPECT_TRUE(set.contains(1)); 631 EXPECT_FALSE(set.contains(foo2)); 632 EXPECT_FALSE(set.contains(2)); 633 } 634 635 } // namespace 636 } // namespace container_internal 637 ABSL_NAMESPACE_END 638 } // namespace absl 639 640 enum Hash : size_t { 641 kStd = 0x1, // std::hash 642 #ifdef _MSC_VER 643 kExtension = kStd, // In MSVC, std::hash == ::hash 644 #else // _MSC_VER 645 kExtension = 0x2, // ::hash (GCC extension) 646 #endif // _MSC_VER 647 }; 648 649 // H is a bitmask of Hash enumerations. 650 // Hashable<H> is hashable via all means specified in H. 651 template <int H> 652 struct Hashable { 653 static constexpr bool HashableBy(Hash h) { return h & H; } 654 }; 655 656 namespace std { 657 template <int H> 658 struct hash<Hashable<H>> { 659 template <class E = Hashable<H>, 660 class = typename std::enable_if<E::HashableBy(kStd)>::type> 661 size_t operator()(E) const { 662 return kStd; 663 } 664 }; 665 } // namespace std 666 667 namespace absl { 668 ABSL_NAMESPACE_BEGIN 669 namespace container_internal { 670 namespace { 671 672 template <class T> 673 size_t Hash(const T& v) { 674 return hash_default_hash<T>()(v); 675 } 676 677 TEST(Delegate, HashDispatch) { 678 EXPECT_EQ(Hash(kStd), Hash(Hashable<kStd>())); 679 } 680 681 } // namespace 682 } // namespace container_internal 683 ABSL_NAMESPACE_END 684 } // namespace absl