hashtable_key_context.h 3.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. // Part of the Carbon Language project, under the Apache License v2.0 with LLVM
  2. // Exceptions. See /LICENSE for license information.
  3. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. #ifndef CARBON_COMMON_HASHTABLE_KEY_CONTEXT_H_
  5. #define CARBON_COMMON_HASHTABLE_KEY_CONTEXT_H_
  6. #include "common/hashing.h"
  7. namespace Carbon {
  8. // Customizable context for keys in hashtables.
  9. //
  10. // This type or customizations matching its API are used with the data
  11. // structures in `map.h` and `set.h`. By providing a custom version of the
  12. // `KeyContext` type parameter to those data structures, users can provide
  13. // either stateless or stateful customization of the two core hashtable key
  14. // operations: hashing and comparison.
  15. //
  16. // The default for hashing uses Carbon's `hashing.h`. Customizations must still
  17. // return a `HashCode` as defined there, and it needs to have the same core
  18. // properties of hashes produced by the `hashing.h` infrastructure.
  19. //
  20. // The default for comparison is `operator==`. The `KeyEq` method is always
  21. // called with a key *stored in the hashtable* as the second or "RHS" parameter.
  22. // This is to allow simplifying the set of overloads needed for heterogeneous
  23. // contexts: only the first, LHS, parameter needs to support different lookup
  24. // key types.
  25. //
  26. // Custom KeyContext types should have the the same API as the default type.
  27. // They can choose to use templates to support heterogeneous key types or not as
  28. // appropriate. The default context can also be used as a base class with only
  29. // one or the other APIs customized.
  30. //
  31. // An important consideration is how the key context is constructed. When the
  32. // key context can be default constructed, hashtable APIs trafficking in keys
  33. // will have overloads that provide a default constructed key context. When the
  34. // context is *not* default constructible, every API that accepts a key will
  35. // also require a context argument to be called, and that argument will be used
  36. // throughout that operation. The intent is to allow callers to provide stateful
  37. // contexts to each API where it would be needed, while managing that state
  38. // outside the hashtable. Often the needed state is trivially part of the
  39. // caller's existing state and needn't be stored separately.
  40. //
  41. // Example for a stateful, customized key context for interned strings:
  42. // ```cpp
  43. // class InternedStringIndexKeyContext {
  44. // public:
  45. // InternedStringIndexKeyContext(
  46. // llvm::ArrayRef<llvm::StringRef> interned_strings)
  47. // : interned_strings_(interned_strings) {}
  48. //
  49. // auto HashKey(llvm::StringRef s, uint64_t seed) const -> HashCode {
  50. // return HashValue(s);
  51. // }
  52. // auto HashKey(int index_key, uint64_t seed) const -> HashCode {
  53. // return HashKey(interned_strings_[index_key]);
  54. // }
  55. //
  56. // auto KeyEq(llvm::StringRef lhs, int rhs_index) const -> bool {
  57. // return lhs == interned_strings_[rhs_index];
  58. // }
  59. // auto KeyEq(int lhs_index, int rhs_index) const -> bool {
  60. // return KeyEq(interned_strings_[lhs_index], rhs_index);
  61. // }
  62. //
  63. // private:
  64. // llvm::ArrayRef<llvm::StringRef> interned_strings_;
  65. // };
  66. // ```
  67. struct DefaultKeyContext {
  68. template <typename KeyT>
  69. auto HashKey(const KeyT& key, uint64_t seed) const -> HashCode {
  70. return HashValue(key, seed);
  71. }
  72. template <typename LHSKeyT, typename RHSKeyT>
  73. auto KeyEq(const LHSKeyT& lhs_key, const RHSKeyT& rhs_key) const -> bool {
  74. return lhs_key == rhs_key;
  75. }
  76. };
  77. } // namespace Carbon
  78. #endif // CARBON_COMMON_HASHTABLE_KEY_CONTEXT_H_