@@ -424,18 +424,30 @@ namespace priv {
424424template <class Policy , class = void >
425425struct hash_policy_traits
426426{
427+ // The type of the keys stored in the hashtable.
428+ using key_type = typename Policy::key_type;
427429private:
428- struct ReturnKey
429- {
430- // We return `Key` here.
431- // When Key=T&, we forward the lvalue reference.
432- // When Key=T, we return by value to avoid a dangling reference.
433- // eg, for string_hash_map.
434- template <class Key , class ... Args>
435- Key operator ()(Key&& k, const Args&...) const {
436- return std::forward<Key>(k);
437- }
438- };
430+ struct ReturnKey {
431+ template <class Key ,
432+ phmap::enable_if_t <std::is_lvalue_reference<Key>::value, int > = 0 >
433+ static key_type& Impl (Key&& k, int ) {
434+ return *const_cast <key_type*>(std::addressof (std::forward<Key>(k)));
435+ }
436+
437+ template <class Key >
438+ static Key Impl (Key&& k, char ) {
439+ return std::forward<Key>(k);
440+ }
441+
442+ // When Key=T&, we forward the lvalue reference.
443+ // When Key=T, we return by value to avoid a dangling reference.
444+ // eg, for string_hash_map.
445+ template <class Key , class ... Args>
446+ auto operator ()(Key&& k, const Args&...) const
447+ -> decltype(Impl(std::forward<Key>(k), 0)) {
448+ return Impl (std::forward<Key>(k), 0 );
449+ }
450+ };
439451
440452 template <class P = Policy, class = void >
441453 struct ConstantIteratorsImpl : std::false_type {};
@@ -448,9 +460,6 @@ struct hash_policy_traits
448460 // The actual object stored in the hash table.
449461 using slot_type = typename Policy::slot_type;
450462
451- // The type of the keys stored in the hashtable.
452- using key_type = typename Policy::key_type;
453-
454463 // The argument type for insertions into the hashtable. This is different
455464 // from value_type for increased performance. See initializer_list constructor
456465 // and insert() member functions for more details.
0 commit comments