5#include <unordered_map> 
    6#include <unordered_set> 
    8#if __cpp_lib_generic_unordered_lookup < 201811L
 
    9#include <boost/unordered_map.hpp> 
   10#include <boost/unordered_set.hpp> 
   13USERVER_NAMESPACE_BEGIN
 
   15namespace utils::impl {
 
   17template <
typename Key>
 
   18struct TransparentHash : 
public std::hash<std::string_view> {
 
   19  static_assert(std::is_convertible_v<Key, std::string_view>,
 
   20                "TransparentHash is only implemented for strings for far");
 
   22  using is_transparent [[maybe_unused]] = 
void;
 
   29#if __cpp_lib_generic_unordered_lookup >= 201811L
 
   30template <
typename Key, 
typename Value, 
typename Hash = TransparentHash<Key>,
 
   31          typename Equal = std::equal_to<>>
 
   32using TransparentMap = std::unordered_map<Key, Value, Hash, Equal>;
 
   34template <
typename Key, 
typename Hash = TransparentHash<Key>,
 
   35          typename Equal = std::equal_to<>>
 
   36using TransparentSet = std::unordered_set<Key, Hash, Equal>;
 
   38template <
typename Key, 
typename Value, 
typename Hash = TransparentHash<Key>,
 
   39          typename Equal = std::equal_to<>>
 
   40using TransparentMap = boost::unordered_map<Key, Value, Hash, Equal>;
 
   42template <
typename Key, 
typename Hash = TransparentHash<Key>,
 
   43          typename Equal = std::equal_to<>>
 
   44using TransparentSet = boost::unordered_set<Key, Hash, Equal>;
 
   47template <
typename TransparentContainer, 
typename Key>
 
   48auto FindTransparent(TransparentContainer&& container, 
const Key& key) {
 
   49  static_assert(!std::is_rvalue_reference_v<TransparentContainer>, 
"Dangling");
 
   50#if __cpp_lib_generic_unordered_lookup >= 201811L
 
   51  return container.find(key);
 
   53  return container.find(key, container.hash_function(), container.key_eq());
 
   57template <
typename TransparentMap, 
typename Key>
 
   58auto* FindTransparentOrNullptr(TransparentMap&& map, 
const Key& key) {
 
   59  static_assert(!std::is_rvalue_reference_v<TransparentMap>, 
"Dangling");
 
   60  const auto iterator = FindTransparent(map, key);
 
   61  return iterator == map.end() ? 
nullptr : &iterator->second;
 
   64template <
typename TransparentMap, 
typename Key, 
typename Value>
 
   65void TransparentInsertOrAssign(TransparentMap& map, Key&& key, Value&& value) {
 
   66  using StoredKey = 
typename TransparentMap::key_type;
 
   68      std::conditional_t<std::is_same_v<std::decay_t<Key>, StoredKey>, Key&&,
 
   70#if __cpp_lib_generic_unordered_lookup >= 201811L
 
   73  map.insert_or_assign(
static_cast<ForwardedKey>(key),
 
   74                       std::forward<Value>(value));
 
   76  const auto iterator = map.find(key, map.hash_function(), map.key_eq());
 
   77  if (iterator != map.end()) {
 
   78    iterator->second = std::forward<Value>(value);
 
   81    map.emplace(
static_cast<ForwardedKey>(key), std::forward<Value>(value));