@@ -22,7 +22,13 @@ namespace Carbon {
2222// `KeyT` can optionally be different from `ValueT`, and if so is used for the
2323// argument to `Lookup`. It must be valid to use both `KeyT` and `ValueT` as
2424// lookup types in the underlying `Set`.
25- template <typename IdT, typename KeyT, typename ValueT = KeyT>
25+ template <typename IdT, typename KeyT, typename ValueT = KeyT,
26+ // Parentheses around the lambda to help clang-format.
27+ auto ValueToKeyFn =
28+ ([](typename ValueStoreTypes<ValueT>::ConstRefType value) ->
29+ typename ValueStoreTypes<ValueT>::ConstRefType {
30+ return value;
31+ })>
2632class CanonicalValueStore {
2733 public:
2834 using KeyType = std::remove_cvref_t <KeyT>;
@@ -75,37 +81,43 @@ class CanonicalValueStore {
7581 Set<IdT, /* SmallSize=*/ 0 , KeyContext> set_;
7682};
7783
78- template <typename IdT, typename KeyT, typename ValueT>
79- class CanonicalValueStore <IdT, KeyT, ValueT>::KeyContext
84+ template <typename IdT, typename KeyT, typename ValueT, auto ValueToKeyFn >
85+ class CanonicalValueStore <IdT, KeyT, ValueT, ValueToKeyFn >::KeyContext
8086 : public TranslatingKeyContext<KeyContext> {
8187 public:
8288 explicit KeyContext (const ValueStore<IdT, ValueType>* values)
8389 : values_(values) {}
8490
8591 // Note that it is safe to return a `const` reference here as the underlying
8692 // object's lifetime is provided by the `ValueStore`.
87- auto TranslateKey (IdT id) const -> ConstRefType { return values_->Get (id); }
93+ auto TranslateKey (IdT id) const
94+ -> llvm::function_traits<decltype(ValueToKeyFn)>::result_t {
95+ return ValueToKeyFn (values_->Get (id));
96+ }
8897
8998 private:
9099 const ValueStore<IdT, ValueType>* values_;
91100};
92101
93- template <typename IdT, typename KeyT, typename ValueT>
94- auto CanonicalValueStore<IdT, KeyT, ValueT>::Add(ValueType value) -> IdT {
102+ template <typename IdT, typename KeyT, typename ValueT, auto ValueToKeyFn>
103+ auto CanonicalValueStore<IdT, KeyT, ValueT, ValueToKeyFn>::Add(ValueType value)
104+ -> IdT {
95105 auto make_key = [&] { return IdT (values_.Add (std::move (value))); };
96- return set_.Insert (value, make_key, KeyContext (&values_)).key ();
106+ return set_.Insert (ValueToKeyFn ( value) , make_key, KeyContext (&values_)).key ();
97107}
98108
99- template <typename IdT, typename KeyT, typename ValueT>
100- auto CanonicalValueStore<IdT, KeyT, ValueT>::Lookup(KeyType key) const -> IdT {
109+ template <typename IdT, typename KeyT, typename ValueT, auto ValueToKeyFn>
110+ auto CanonicalValueStore<IdT, KeyT, ValueT, ValueToKeyFn>::Lookup(
111+ KeyType key) const -> IdT {
101112 if (auto result = set_.Lookup (key, KeyContext (&values_))) {
102113 return result.key ();
103114 }
104115 return IdT::None;
105116}
106117
107- template <typename IdT, typename KeyT, typename ValueT>
108- auto CanonicalValueStore<IdT, KeyT, ValueT>::Reserve(size_t size) -> void {
118+ template <typename IdT, typename KeyT, typename ValueT, auto ValueToKeyFn>
119+ auto CanonicalValueStore<IdT, KeyT, ValueT, ValueToKeyFn>::Reserve(size_t size)
120+ -> void {
109121 // Compute the resulting new insert count using the size of values -- the
110122 // set doesn't have a fast to compute current size.
111123 if (size > values_.size ()) {
0 commit comments