| 907 | template <bool IsFlat, size_t MaxLoadFactor100, typename Key, typename T, typename Hash, |
| 908 | typename KeyEqual> |
| 909 | class Table |
| 910 | : public WrapHash<Hash>, |
| 911 | public WrapKeyEqual<KeyEqual>, |
| 912 | detail::NodeAllocator< |
| 913 | typename std::conditional< |
| 914 | std::is_void<T>::value, Key, |
| 915 | robin_hood::pair<typename std::conditional<IsFlat, Key, Key const>::type, T>>::type, |
| 916 | 4, 16384, IsFlat> { |
| 917 | public: |
| 918 | static constexpr bool is_flat = IsFlat; |
| 919 | static constexpr bool is_map = !std::is_void<T>::value; |
| 920 | static constexpr bool is_set = !is_map; |
| 921 | static constexpr bool is_transparent = |
| 922 | has_is_transparent<Hash>::value && has_is_transparent<KeyEqual>::value; |
| 923 | |
| 924 | using key_type = Key; |
| 925 | using mapped_type = T; |
| 926 | using value_type = typename std::conditional< |
| 927 | is_set, Key, |
| 928 | robin_hood::pair<typename std::conditional<is_flat, Key, Key const>::type, T>>::type; |
| 929 | using size_type = size_t; |
| 930 | using hasher = Hash; |
| 931 | using key_equal = KeyEqual; |
| 932 | using Self = Table<IsFlat, MaxLoadFactor100, key_type, mapped_type, hasher, key_equal>; |
| 933 | |
| 934 | private: |
| 935 | static_assert(MaxLoadFactor100 > 10 && MaxLoadFactor100 < 100, |
| 936 | "MaxLoadFactor100 needs to be >10 && < 100"); |
| 937 | |
| 938 | using WHash = WrapHash<Hash>; |
| 939 | using WKeyEqual = WrapKeyEqual<KeyEqual>; |
| 940 | |
| 941 | // configuration defaults |
| 942 | |
| 943 | // make sure we have 8 elements, needed to quickly rehash mInfo |
| 944 | static constexpr size_t InitialNumElements = sizeof(uint64_t); |
| 945 | static constexpr uint32_t InitialInfoNumBits = 5; |
| 946 | static constexpr uint8_t InitialInfoInc = 1U << InitialInfoNumBits; |
| 947 | static constexpr size_t InfoMask = InitialInfoInc - 1U; |
| 948 | static constexpr uint8_t InitialInfoHashShift = 0; |
| 949 | using DataPool = detail::NodeAllocator<value_type, 4, 16384, IsFlat>; |
| 950 | |
| 951 | // type needs to be wider than uint8_t. |
| 952 | using InfoType = uint32_t; |
| 953 | |
| 954 | // DataNode //////////////////////////////////////////////////////// |
| 955 | |
| 956 | // Primary template for the data node. We have special implementations for small and big |
| 957 | // objects. For large objects it is assumed that swap() is fairly slow, so we allocate these |
| 958 | // on the heap so swap merely swaps a pointer. |
| 959 | template <typename M, bool> |
| 960 | class DataNode {}; |
| 961 | |
| 962 | // Small: just allocate on the stack. |
| 963 | template <typename M> |
| 964 | class DataNode<M, true> final { |
| 965 | public: |
| 966 | template <typename... Args> |