@@ -20,15 +20,9 @@ namespace Carbon {
2020// `ValueT` represents the type being stored.
2121//
2222// `KeyT` can optionally be different from `ValueT`, and if so is used for the
23- // argument to `Lookup`. It must be valid to use both `KeyT` and `ValueT` as
24- // lookup types in the underlying `Set`.
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- })>
23+ // argument to `Lookup`. In this case, `ValueT` must provide a `GetAsKey` member
24+ // function that returns the corresponding key.
25+ template <typename IdT, typename KeyT, typename ValueT = KeyT>
3226class CanonicalValueStore {
3327 public:
3428 using KeyType = std::remove_cvref_t <KeyT>;
@@ -79,47 +73,55 @@ class CanonicalValueStore {
7973 private:
8074 class KeyContext ;
8175
76+ static auto GetAsKey (ConstRefType value) -> ConstRefType
77+ requires std::same_as<KeyT, ValueT>
78+ {
79+ return value;
80+ }
81+
82+ template <typename T>
83+ static auto GetAsKey (T&& value) -> decltype(value.GetAsKey()) {
84+ return value.GetAsKey ();
85+ }
86+
8287 ValueStore<IdT, ValueType> values_;
8388 Set<IdT, /* SmallSize=*/ 0 , KeyContext> set_;
8489};
8590
86- template <typename IdT, typename KeyT, typename ValueT, auto ValueToKeyFn >
87- class CanonicalValueStore <IdT, KeyT, ValueT, ValueToKeyFn >::KeyContext
91+ template <typename IdT, typename KeyT, typename ValueT>
92+ class CanonicalValueStore <IdT, KeyT, ValueT>::KeyContext
8893 : public TranslatingKeyContext<KeyContext> {
8994 public:
9095 explicit KeyContext (const ValueStore<IdT, ValueType>* values)
9196 : values_(values) {}
9297
93- // Note that it is safe to return a `const` reference here as the underlying
94- // object's lifetime is provided by the `ValueStore`.
98+ // Note that it is safe to return a reference here as the underlying object's
99+ // lifetime is provided by the `ValueStore`.
95100 auto TranslateKey (IdT id) const
96- -> llvm::function_traits<decltype(ValueToKeyFn)>::result_t {
97- return ValueToKeyFn (values_->Get (id));
101+ -> decltype(GetAsKey(std::declval<ConstRefType>())) {
102+ return GetAsKey (values_->Get (id));
98103 }
99104
100105 private:
101106 const ValueStore<IdT, ValueType>* values_;
102107};
103108
104- template <typename IdT, typename KeyT, typename ValueT, auto ValueToKeyFn>
105- auto CanonicalValueStore<IdT, KeyT, ValueT, ValueToKeyFn>::Add(ValueType value)
106- -> IdT {
109+ template <typename IdT, typename KeyT, typename ValueT>
110+ auto CanonicalValueStore<IdT, KeyT, ValueT>::Add(ValueType value) -> IdT {
107111 auto make_key = [&] { return IdT (values_.Add (std::move (value))); };
108- return set_.Insert (ValueToKeyFn (value), make_key, KeyContext (&values_)).key ();
112+ return set_.Insert (GetAsKey (value), make_key, KeyContext (&values_)).key ();
109113}
110114
111- template <typename IdT, typename KeyT, typename ValueT, auto ValueToKeyFn>
112- auto CanonicalValueStore<IdT, KeyT, ValueT, ValueToKeyFn>::Lookup(
113- KeyType key) const -> IdT {
115+ template <typename IdT, typename KeyT, typename ValueT>
116+ auto CanonicalValueStore<IdT, KeyT, ValueT>::Lookup(KeyType key) const -> IdT {
114117 if (auto result = set_.Lookup (key, KeyContext (&values_))) {
115118 return result.key ();
116119 }
117120 return IdT::None;
118121}
119122
120- template <typename IdT, typename KeyT, typename ValueT, auto ValueToKeyFn>
121- auto CanonicalValueStore<IdT, KeyT, ValueT, ValueToKeyFn>::Reserve(size_t size)
122- -> void {
123+ template <typename IdT, typename KeyT, typename ValueT>
124+ auto CanonicalValueStore<IdT, KeyT, ValueT>::Reserve(size_t size) -> void {
123125 // Compute the resulting new insert count using the size of values -- the
124126 // set doesn't have a fast to compute current size.
125127 if (size > values_.size ()) {
0 commit comments