Changeset 379ce989 in mainline


Ignore:
Timestamp:
2018-07-05T21:41:21Z (6 years ago)
Author:
Dzejrou <dzejrou@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
99bf4c4
Parents:
f185504
git-author:
Dzejrou <dzejrou@…> (2018-04-25 21:00:16)
git-committer:
Dzejrou <dzejrou@…> (2018-07-05 21:41:21)
Message:

cpp: added unordered_multimap, boy is that easy with our uber table

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/cpp/include/impl/unordered_map.hpp

    rf185504 r379ce989  
    850850        class Alloc = allocator<pair<const Key, Value>>
    851851    >
    852     class unordered_multimap;
     852    class unordered_multimap
     853    {
     854        public:
     855            using key_type        = Key;
     856            using mapped_type     = Value;
     857            using value_type      = pair<const key_type, mapped_type>;
     858            using hasher          = Hash;
     859            using key_equal       = Pred;
     860            using allocator_type  = Alloc;
     861            using pointer         = typename allocator_traits<allocator_type>::pointer;
     862            using const_pointer   = typename allocator_traits<allocator_type>::const_pointer;
     863            using reference       = value_type&;
     864            using const_reference = const value_type&;
     865            using size_type       = size_t;
     866            using difference_type = ptrdiff_t;
     867
     868            using iterator             = aux::hash_table_iterator<
     869                value_type, reference, pointer, size_type
     870            >;
     871            using const_iterator       = aux::hash_table_const_iterator<
     872                value_type, const_reference, const_pointer, size_type
     873            >;
     874            using local_iterator       = aux::hash_table_local_iterator<
     875                value_type, reference, pointer
     876            >;
     877            using const_local_iterator = aux::hash_table_const_local_iterator<
     878                value_type, const_reference, const_pointer
     879            >;
     880
     881            unordered_multimap()
     882                : unordered_multimap{default_bucket_count_}
     883            { /* DUMMY BODY */ }
     884
     885            explicit unordered_multimap(size_type bucket_count,
     886                                   const hasher& hf = hasher{},
     887                                   const key_equal& eql = key_equal{},
     888                                   const allocator_type& alloc = allocator_type{})
     889                : table_{bucket_count, hf, eql}, allocator_{alloc}
     890            { /* DUMMY BODY */ }
     891
     892            template<class InputIterator>
     893            unordered_multimap(InputIterator first, InputIterator last,
     894                          size_type bucket_count = default_bucket_count_,
     895                          const hasher& hf = hasher{},
     896                          const key_equal& eql = key_equal{},
     897                          const allocator_type& alloc = allocator_type{})
     898                : unordered_multimap{bucket_count, hf, eql, alloc}
     899            {
     900                insert(first, last);
     901            }
     902
     903            unordered_multimap(const unordered_multimap& other)
     904                : unordered_multimap{other, other.allocator_}
     905            { /* DUMMY BODY */ }
     906
     907            unordered_multimap(unordered_multimap&& other)
     908                : table_{move(other.table_)}, allocator_{move(other.allocator_)}
     909            { /* DUMMY BODY */ }
     910
     911            explicit unordered_multimap(const allocator_type& alloc)
     912                : table_{default_bucket_count_}, allocator_{alloc}
     913            { /* DUMMY BODY */ }
     914
     915            unordered_multimap(const unordered_multimap& other, const allocator_type& alloc)
     916                : table_{other.table_}, allocator_{alloc}
     917            { /* DUMMY BODY */ }
     918
     919            unordered_multimap(unordered_multimap&& other, const allocator_type& alloc)
     920                : table_{move(other.table_)}, allocator_{alloc}
     921            { /* DUMMY BODY */ }
     922
     923            unordered_multimap(initializer_list<value_type> init,
     924                          size_type bucket_count = default_bucket_count_,
     925                          const hasher& hf = hasher{},
     926                          const key_equal& eql = key_equal{},
     927                          const allocator_type& alloc = allocator_type{})
     928                : unordered_multimap{bucket_count, hf, eql, alloc}
     929            {
     930                insert(init.begin(), init.end());
     931            }
     932
     933            unordered_multimap(size_type bucket_count, const allocator_type& alloc)
     934                : unordered_multimap{bucket_count, hasher{}, key_equal{}, alloc}
     935            { /* DUMMY BODY */ }
     936
     937            unordered_multimap(size_type bucket_count, const hasher& hf, const allocator_type& alloc)
     938                : unordered_multimap{bucket_count, hf, key_equal{}, alloc}
     939            { /* DUMMY BODY */ }
     940
     941            template<class InputIterator>
     942            unordered_multimap(InputIterator first, InputIterator last,
     943                          size_type bucket_count, const allocator_type& alloc)
     944                : unordered_multimap{first, last, bucket_count, hasher{}, key_equal{}, alloc}
     945            { /* DUMMY BODY */ }
     946
     947            template<class InputIterator>
     948            unordered_multimap(InputIterator first, InputIterator last,
     949                          size_type bucket_count, const hasher& hf, const allocator_type& alloc)
     950                : unordered_multimap{first, last, bucket_count, hf, key_equal{}, alloc}
     951            { /* DUMMY BODY */ }
     952
     953            unordered_multimap(initializer_list<value_type> init, size_type bucket_count,
     954                          const allocator_type& alloc)
     955                : unordered_multimap{init, bucket_count, hasher{}, key_equal{}, alloc}
     956            { /* DUMMY BODY */ }
     957
     958            unordered_multimap(initializer_list<value_type> init, size_type bucket_count,
     959                          const hasher& hf, const allocator_type& alloc)
     960                : unordered_multimap{init, bucket_count, hf, key_equal{}, alloc}
     961            { /* DUMMY BODY */ }
     962
     963            ~unordered_multimap()
     964            { /* DUMMY BODY */ }
     965
     966            unordered_multimap& operator=(const unordered_multimap& other)
     967            {
     968                table_ = other.table_;
     969                allocator_ = other.allocator_;
     970
     971                return *this;
     972            }
     973
     974            unordered_multimap& operator=(unordered_multimap&& other)
     975                noexcept(allocator_traits<allocator_type>::is_always_equal::value &&
     976                         is_nothrow_move_assignable<hasher>::value &&
     977                         is_nothrow_move_assignable<key_equal>::value)
     978            {
     979                table_ = move(other.table_);
     980                allocator_ = move(other.allocator_);
     981
     982                return *this;
     983            }
     984
     985            unordered_multimap& operator=(initializer_list<value_type>& init)
     986            {
     987                table_.clear();
     988                table_.reserve(init.size());
     989
     990                insert(init.begin(), init.end());
     991
     992                return *this;
     993            }
     994
     995            allocator_type get_allocator() const noexcept
     996            {
     997                return allocator_;
     998            }
     999
     1000            bool empty() const noexcept
     1001            {
     1002                return table_.empty();
     1003            }
     1004
     1005            size_type size() const noexcept
     1006            {
     1007                return table_.size();
     1008            }
     1009
     1010            size_type max_size() const noexcept
     1011            {
     1012                return table_.max_size(allocator_);
     1013            }
     1014
     1015            iterator begin() noexcept
     1016            {
     1017                return table_.begin();
     1018            }
     1019
     1020            const_iterator begin() const noexcept
     1021            {
     1022                return table_.begin();
     1023            }
     1024
     1025            iterator end() noexcept
     1026            {
     1027                return table_.end();
     1028            }
     1029
     1030            const_iterator end() const noexcept
     1031            {
     1032                return table_.end();
     1033            }
     1034
     1035            const_iterator cbegin() const noexcept
     1036            {
     1037                return table_.cbegin();
     1038            }
     1039
     1040            const_iterator cend() const noexcept
     1041            {
     1042                return table_.cend();
     1043            }
     1044
     1045            template<class... Args>
     1046            pair<iterator, bool> emplace(Args&&... args)
     1047            {
     1048                table_.increment_size();
     1049
     1050                auto val = value_type{forward<Args>(args)...};
     1051                auto key = table_.get_key(val);
     1052                auto spot = table_.find_insertion_spot(key);
     1053                auto bucket = get<0>(spot);
     1054                auto idx = get<2>(spot);
     1055
     1056                if (!bucket)
     1057                    return make_pair(end(), false);
     1058
     1059                auto target = table_.find_node_or_return_head(key, *bucket);
     1060                auto node = new node_type{move(val)};
     1061                if (target && table_.keys_equal(key, target->value))
     1062                    target->append(node);
     1063                else
     1064                    bucket->prepend(node);
     1065
     1066                return make_pair(iterator{
     1067                    table_.table(), idx,
     1068                    table_.bucket_count(),
     1069                    node
     1070                }, true);
     1071            }
     1072
     1073            template<class... Args>
     1074            iterator emplace_hint(const_iterator, Args&&... args)
     1075            {
     1076                return emplace(forward<Args>(args)...).first;
     1077            }
     1078
     1079            pair<iterator, bool> insert(const value_type& val)
     1080            {
     1081                table_.increment_size();
     1082
     1083                auto key = table_.get_key(val);
     1084                auto spot = table_.find_insertion_spot(key);
     1085                auto bucket = get<0>(spot);
     1086                auto idx = get<2>(spot);
     1087
     1088                if (!bucket)
     1089                    return make_pair(end(), false);
     1090
     1091                auto target = table_.find_node_or_return_head(key, *bucket);
     1092                auto node = new node_type{val};
     1093                if (target && table_.keys_equal(key, target->value))
     1094                    target->append(node);
     1095                else
     1096                    bucket->prepend(node);
     1097
     1098                return make_pair(iterator{
     1099                    table_.table(), idx,
     1100                    table_.bucket_count(),
     1101                    node
     1102                }, true);
     1103            }
     1104
     1105            pair<iterator, bool> insert(value_type&& val)
     1106            {
     1107                table_.increment_size();
     1108
     1109                auto key = table_.get_key(val);
     1110                auto spot = table_.find_insertion_spot(key);
     1111                auto bucket = get<0>(spot);
     1112                auto idx = get<2>(spot);
     1113
     1114                if (!bucket)
     1115                    return make_pair(end(), false);
     1116
     1117                auto target = table_.find_node_or_return_head(key, *bucket);
     1118                auto node = new node_type{forward<value_type>(val)};
     1119                if (target && table_.keys_equal(key, target->value))
     1120                    target->append(node);
     1121                else
     1122                    bucket->prepend(node);
     1123
     1124                return make_pair(iterator{
     1125                    table_.table(), idx,
     1126                    table_.bucket_count(),
     1127                    node
     1128                }, true);
     1129            }
     1130
     1131            template<
     1132                class T,
     1133                class = enable_if_t<is_constructible_v<value_type, T&&>, void>
     1134            >
     1135            pair<iterator, bool> insert(T&& val)
     1136            {
     1137                return emplace(forward<T>(val));
     1138            }
     1139
     1140            iterator insert(const_iterator, const value_type& val)
     1141            {
     1142                return insert(val).first;
     1143            }
     1144
     1145            iterator insert(const_iterator, value_type&& val)
     1146            {
     1147                return insert(forward<value_type>(val)).first;
     1148            }
     1149
     1150            template<
     1151                class T,
     1152                class = enable_if_t<is_constructible_v<value_type, T&&>, void>
     1153            >
     1154            iterator insert(const_iterator hint, T&& val)
     1155            {
     1156                return emplace_hint(hint, forward<T>(val));
     1157            }
     1158
     1159            template<class InputIterator>
     1160            void insert(InputIterator first, InputIterator last)
     1161            {
     1162                while (first != last)
     1163                    insert(*first++);
     1164            }
     1165
     1166            void insert(initializer_list<value_type> init)
     1167            {
     1168                insert(init.begin(), init.end());
     1169            }
     1170
     1171            iterator erase(const_iterator position)
     1172            {
     1173                return table_.erase(position);
     1174            }
     1175
     1176            size_type erase(const key_type& key)
     1177            {
     1178                return table_.erase(key);
     1179            }
     1180
     1181            iterator erase(const_iterator first, const_iterator last)
     1182            {
     1183                while (first != last)
     1184                    first = erase(first);
     1185
     1186                return iterator{
     1187                    table_.table(), first.idx(),
     1188                    table_.bucket_count(), table_.head(first.idx())
     1189                };
     1190            }
     1191
     1192            void clear() noexcept
     1193            {
     1194                table_.clear();
     1195            }
     1196
     1197            void swap(unordered_multimap& other)
     1198                noexcept(allocator_traits<allocator_type>::is_always_equal::value &&
     1199                         noexcept(std::swap(declval<hasher>(), declval<hasher>())) &&
     1200                         noexcept(std::swap(declval<key_equal>(), declval<key_equal>())))
     1201            {
     1202                table_.swap(other.table_);
     1203                std::swap(allocator_, other.allocator_);
     1204            }
     1205
     1206            hasher hash_function() const
     1207            {
     1208                return table_.hash_function();
     1209            }
     1210
     1211            key_equal key_eq() const
     1212            {
     1213                return table_.key_eq();
     1214            }
     1215
     1216            iterator find(const key_type& key)
     1217            {
     1218                return table_.find(key);
     1219            }
     1220
     1221            const_iterator find(const key_type& key) const
     1222            {
     1223                return table_.find(key);
     1224            }
     1225
     1226            size_type count(const key_type& key) const
     1227            {
     1228                return table_.count(key);
     1229            }
     1230
     1231            pair<iterator, iterator> equal_range(const key_type& key)
     1232            {
     1233                return table_.equal_range(key);
     1234            }
     1235
     1236            pair<const_iterator, const_iterator> equal_range(const key_type& key) const
     1237            {
     1238                return table_.equal_range(key);
     1239            }
     1240
     1241            size_type bucket_count() const noexcept
     1242            {
     1243                return table_.bucket_count();
     1244            }
     1245
     1246            size_type max_bucket_count() const noexcept
     1247            {
     1248                return table_.max_bucket_count();
     1249            }
     1250
     1251            size_type bucket_size(size_type idx) const
     1252            {
     1253                return table_.bucket_size(idx);
     1254            }
     1255
     1256            size_type bucket(const key_type& key) const
     1257            {
     1258                return table_.bucket(key);
     1259            }
     1260
     1261            local_iterator begin(size_type idx)
     1262            {
     1263                return table_.begin(idx);
     1264            }
     1265
     1266            const_local_iterator begin(size_type idx) const
     1267            {
     1268                return table_.begin(idx);
     1269            }
     1270
     1271            local_iterator end(size_type idx)
     1272            {
     1273                return table_.end(idx);
     1274            }
     1275
     1276            const_local_iterator end(size_type idx) const
     1277            {
     1278                return table_.end(idx);
     1279            }
     1280
     1281            const_local_iterator cbegin(size_type idx) const
     1282            {
     1283                return table_.cbegin(idx);
     1284            }
     1285
     1286            const_local_iterator cend(size_type idx) const
     1287            {
     1288                return table_.cend(idx);
     1289            }
     1290
     1291            float load_factor() const noexcept
     1292            {
     1293                return table_.load_factor();
     1294            }
     1295
     1296            float max_load_factor() const noexcept
     1297            {
     1298                return table_.max_load_factor();
     1299            }
     1300
     1301            void max_load_factor(float factor)
     1302            {
     1303                table_.max_load_factor(factor);
     1304            }
     1305
     1306            void rehash(size_type bucket_count)
     1307            {
     1308                table_.rehash(bucket_count);
     1309            }
     1310
     1311            void reserve(size_type count)
     1312            {
     1313                table_.reserve(count);
     1314            }
     1315
     1316        private:
     1317            using table_type = aux::hash_table<
     1318                value_type, key_type, aux::key_value_key_extractor<key_type, mapped_type>,
     1319                hasher, key_equal, allocator_type, size_type,
     1320                iterator, const_iterator, local_iterator, const_local_iterator,
     1321                aux::hash_single_policy
     1322            >;
     1323            using node_type = typename table_type::node_type;
     1324
     1325            table_type table_;
     1326            allocator_type allocator_;
     1327
     1328            static constexpr size_type default_bucket_count_{16};
     1329
     1330            template<class K, class V, class H, class P, class A>
     1331            friend bool operator==(unordered_multimap<K, V, H, P, A>&,
     1332                                   unordered_multimap<K, V, H, P, A>&);
     1333    };
    8531334
    8541335    template<class Key, class Value, class Hash, class Pred, class Alloc>
Note: See TracChangeset for help on using the changeset viewer.