heterogeneous_containers.h (3687B)
1 // SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin <stenzek@gmail.com> 2 // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0) 3 4 /** 5 * Provides a map template which doesn't require heap allocations for lookups. 6 */ 7 8 #pragma once 9 10 #include "types.h" 11 #include <map> 12 #include <set> 13 #include <string> 14 #include <unordered_map> 15 #include <unordered_set> 16 17 namespace detail { 18 struct transparent_string_hash 19 { 20 using is_transparent = void; 21 22 std::size_t operator()(const std::string_view& v) const { return std::hash<std::string_view>{}(v); } 23 std::size_t operator()(const std::string& s) const { return std::hash<std::string>{}(s); } 24 std::size_t operator()(const char* s) const { return operator()(std::string_view(s)); } 25 }; 26 27 struct transparent_string_equal 28 { 29 using is_transparent = void; 30 31 bool operator()(const std::string& lhs, const std::string_view& rhs) const { return lhs == rhs; } 32 bool operator()(const std::string& lhs, const std::string& rhs) const { return lhs == rhs; } 33 bool operator()(const std::string& lhs, const char* rhs) const { return lhs == rhs; } 34 bool operator()(const std::string_view& lhs, const std::string& rhs) const { return lhs == rhs; } 35 bool operator()(const char* lhs, const std::string& rhs) const { return lhs == rhs; } 36 }; 37 38 struct transparent_string_less 39 { 40 using is_transparent = void; 41 42 bool operator()(const std::string& lhs, const std::string_view& rhs) const { return lhs < rhs; } 43 bool operator()(const std::string& lhs, const std::string& rhs) const { return lhs < rhs; } 44 bool operator()(const std::string& lhs, const char* rhs) const { return lhs < rhs; } 45 bool operator()(const std::string_view& lhs, const std::string& rhs) const { return lhs < rhs; } 46 bool operator()(const char* lhs, const std::string& rhs) const { return lhs < rhs; } 47 }; 48 } // namespace detail 49 50 template<typename ValueType> 51 using StringMap = std::map<std::string, ValueType, detail::transparent_string_less>; 52 template<typename ValueType> 53 using StringMultiMap = std::multimap<std::string, ValueType, detail::transparent_string_less>; 54 using StringSet = std::set<std::string, detail::transparent_string_less>; 55 using StringMultiSet = std::multiset<std::string, detail::transparent_string_less>; 56 57 #if defined(__cpp_lib_generic_unordered_lookup) && __cpp_lib_generic_unordered_lookup >= 201811L 58 template<typename ValueType> 59 using UnorderedStringMap = 60 std::unordered_map<std::string, ValueType, detail::transparent_string_hash, detail::transparent_string_equal>; 61 template<typename ValueType> 62 using UnorderedStringMultimap = 63 std::unordered_multimap<std::string, ValueType, detail::transparent_string_hash, detail::transparent_string_equal>; 64 using UnorderedStringSet = 65 std::unordered_set<std::string, detail::transparent_string_hash, detail::transparent_string_equal>; 66 using UnorderedStringMultiSet = 67 std::unordered_multiset<std::string, detail::transparent_string_hash, detail::transparent_string_equal>; 68 69 template<typename ValueType> 70 using PreferUnorderedStringMap = UnorderedStringMap<ValueType>; 71 template<typename ValueType> 72 using PreferUnorderedStringMultimap = UnorderedStringMultimap<ValueType>; 73 using PreferUnorderedStringSet = UnorderedStringSet; 74 using PreferUnorderedStringMultiSet = UnorderedStringMultiSet; 75 #else 76 77 #pragma message "__cpp_lib_generic_unordered_lookup is missing, performance will be slower." 78 79 // GCC 10 doesn't support generic_unordered_lookup... 80 template<typename ValueType> 81 using PreferUnorderedStringMap = StringMap<ValueType>; 82 template<typename ValueType> 83 using PreferUnorderedStringMultimap = StringMultiMap<ValueType>; 84 using PreferUnorderedStringSet = StringSet; 85 using PreferUnorderedStringMultiSet = StringMultiSet; 86 87 #endif