diff --git a/examples/btree.cc b/examples/btree.cc index ba65f63..60f187a 100644 --- a/examples/btree.cc +++ b/examples/btree.cc @@ -2,29 +2,45 @@ #include #include -using phmap::btree_map; -using phmap::btree_set; - int main() { - btree_map persons = + // initialise map with some values using an initializer_list + phmap::btree_map map = { { "John", 35 }, { "Jane", 32 }, { "Joe", 30 }, }; - for (auto& p: persons) - std::cout << p.first << " (" << p.second << ")" << '\n'; + // add a couple more values using operator[]() + map["lucy"] = 18; + map["Andre"] = 20; - // Create a btree_set of three floats (that map to strings) - using X = std::tuple; - btree_set email; - - // Iterate and print keys and values - for (int i=0; i<10; ++i) - email.insert(X((float)i, "aha")); + map.insert(std::make_pair("Alex", 16)); + map.emplace("Emily", 18); // emplace uses pair template constructor - for (auto& e: email) - std::cout << std::get<0>(e) << ", " << std::get<1>(e) << '\n'; - return 0; + for (auto& p: map) + std::cout << p.first << ", " << p.second << '\n'; + + phmap::btree_map map2; + + map2.emplace(std::piecewise_construct, std::forward_as_tuple(0), std::forward_as_tuple(10, 'c')); + map2.try_emplace(1, 10, 'a'); // phmap::btree_map supports c++17 API + + for (auto& p: map2) + std::cout << p.first << ", " << p.second << '\n'; + + // create a btree_set of tuples + using X = std::tuple; + phmap::btree_set set; + + for (int i=0; i<10; ++i) + set.insert(X((float)i, std::to_string(i))); + set.emplace(15.0f, "15"); + + set.erase(X(1.0f, "1")); + + for (auto& e: set) + std::cout << std::get<0>(e) << ", \"" << std::get<1>(e) << "\" \n"; + + return 0; } diff --git a/parallel_hashmap/btree.h b/parallel_hashmap/btree.h index 084e987..4838b91 100644 --- a/parallel_hashmap/btree.h +++ b/parallel_hashmap/btree.h @@ -1197,10 +1197,10 @@ namespace container_internal { void clear_child(size_type i) { phmap::container_internal::SanitizerPoisonObject(&mutable_child(i)); } - void set_child(int i, btree_node *c) { + void set_child(size_type i, btree_node *c) { phmap::container_internal::SanitizerUnpoisonObject(&mutable_child(i)); mutable_child(i) = c; - c->set_position(i); + c->set_position((field_type)i); } void init_child(int i, btree_node *c) { set_child(i, c); diff --git a/parallel_hashmap/phmap.h b/parallel_hashmap/phmap.h index 297c6c2..b169c03 100644 --- a/parallel_hashmap/phmap.h +++ b/parallel_hashmap/phmap.h @@ -55,6 +55,12 @@ #include #endif +#ifdef _MSC_VER + #pragma warning(push) + // warning C4820: '6' bytes padding added after data member + #pragma warning(disable : 4820) +#endif + namespace phmap { namespace container_internal { @@ -268,7 +274,7 @@ inline size_t H1(size_t hash, const ctrl_t* ) { #endif -inline ctrl_t H2(size_t hash) { return hash & 0x7F; } +inline ctrl_t H2(size_t hash) { return (ctrl_t)(hash & 0x7F); } inline bool IsEmpty(ctrl_t c) { return c == kEmpty; } inline bool IsFull(ctrl_t c) { return c >= 0; } @@ -313,7 +319,7 @@ struct GroupSse2Impl // Returns a bitmask representing the positions of slots that match hash. // ---------------------------------------------------------------------- BitMask Match(h2_t hash) const { - auto match = _mm_set1_epi8(hash); + auto match = _mm_set1_epi8((char)hash); return BitMask( _mm_movemask_epi8(_mm_cmpeq_epi8(match, ctrl))); } @@ -461,6 +467,12 @@ inline size_t NormalizeCapacity(size_t n) return n ? ~size_t{} >> LeadingZeros(n) : 1; } +#ifdef _MSC_VER + #pragma warning(push) + // warning C4127: conditional expression is constant + #pragma warning(disable : 4127) +#endif + // -------------------------------------------------------------------------- // We use 7/8th as maximum load factor. // For 16-wide groups, that gives an average of two empty slots per group. @@ -469,7 +481,7 @@ inline size_t CapacityToGrowth(size_t capacity) { assert(IsValidCapacity(capacity)); // `capacity*7/8` - if (Group::kWidth == 8 && capacity == 7) { + PHMAP_IF_CONSTEXPR (Group::kWidth == 8 && capacity == 7) { // x-x/8 does not work when x==7. return 6; } @@ -483,13 +495,17 @@ inline size_t CapacityToGrowth(size_t capacity) inline size_t GrowthToLowerboundCapacity(size_t growth) { // `growth*8/7` - if (Group::kWidth == 8 && growth == 7) { + PHMAP_IF_CONSTEXPR (Group::kWidth == 8 && growth == 7) { // x+(x-1)/7 does not work when x==7. return 8; } return growth + static_cast((static_cast(growth) - 1) / 7); } +#ifdef _MSC_VER + #pragma warning(pop) +#endif + namespace hashtable_debug_internal { // If it is a map, call get<0>(). @@ -4347,4 +4363,9 @@ public: } // namespace phmap +#ifdef _MSC_VER + #pragma warning(pop) +#endif + + #endif // phmap_h_guard_ diff --git a/parallel_hashmap/phmap_base.h b/parallel_hashmap/phmap_base.h index 895216c..418a132 100644 --- a/parallel_hashmap/phmap_base.h +++ b/parallel_hashmap/phmap_base.h @@ -246,17 +246,6 @@ struct is_trivially_destructible : std::integral_constant::value> { -#ifdef PHMAP_HAVE_STD_IS_TRIVIALLY_DESTRUCTIBLE -private: - static constexpr bool compliant = std::is_trivially_destructible::value == - is_trivially_destructible::value; - static_assert(compliant || std::is_trivially_destructible::value, - "Not compliant with std::is_trivially_destructible; " - "Standard: false, Implementation: true"); - static_assert(compliant || !std::is_trivially_destructible::value, - "Not compliant with std::is_trivially_destructible; " - "Standard: true, Implementation: false"); -#endif }; // --------------------------------------------------------------------------- @@ -2846,6 +2835,12 @@ struct KeyArg using type = key_type; }; +#ifdef _MSC_VER + #pragma warning(push) + // warning C4820: '6' bytes padding added after data member + #pragma warning(disable : 4820) +#endif + // The node_handle concept from C++17. // We specialize node_handle for sets and maps. node_handle_base holds the // common API of both. @@ -2900,6 +2895,9 @@ protected: PolicyTraits::transfer(alloc(), slot(), s); } + node_handle_base(const node_handle_base&) = delete; + node_handle_base& operator=(const node_handle_base&) = delete; + void destroy() { if (!empty()) { PolicyTraits::destroy(alloc(), slot()); @@ -2921,10 +2919,13 @@ protected: private: phmap::optional alloc_; - mutable phmap::aligned_storage_t - slot_space_; + mutable phmap::aligned_storage_t slot_space_; }; +#ifdef _MSC_VER + #pragma warning(pop) +#endif + // For sets. // --------- template {}; namespace phmap { namespace container_internal { +#ifdef _MSC_VER + #pragma warning(push) + // warning warning C4324: structure was padded due to alignment specifier + #pragma warning(disable : 4324) +#endif // ---------------------------------------------------------------------------- @@ -4477,6 +4483,10 @@ void Deallocate(Alloc* alloc, void* p, size_t n) { (n + sizeof(M) - 1) / sizeof(M)); } +#ifdef _MSC_VER + #pragma warning(pop) +#endif + // Helper functions for asan and msan. // ---------------------------------------------------------------------------- inline void SanitizerPoisonMemoryRegion(const void* m, size_t s) { @@ -4714,6 +4724,9 @@ union map_slot_type { map_slot_type() {} ~map_slot_type() = delete; + map_slot_type(const map_slot_type&) = delete; + map_slot_type& operator=(const map_slot_type&) = delete; + using value_type = std::pair; using mutable_value_type = std::pair; diff --git a/parallel_hashmap/phmap_bits.h b/parallel_hashmap/phmap_bits.h index 8e4f017..f28e686 100644 --- a/parallel_hashmap/phmap_bits.h +++ b/parallel_hashmap/phmap_bits.h @@ -279,7 +279,7 @@ PHMAP_BASE_INTERNAL_FORCEINLINE int CountLeadingZeros64(uint64_t n) { // MSVC does not have __buitin_clzll. Use _BitScanReverse64. unsigned long result = 0; // NOLINT(runtime/int) if (_BitScanReverse64(&result, n)) { - return 63 - result; + return (int)(63 - result); } return 64; #elif defined(_MSC_VER) @@ -322,7 +322,7 @@ PHMAP_BASE_INTERNAL_FORCEINLINE int CountLeadingZeros32(uint32_t n) { #if defined(_MSC_VER) unsigned long result = 0; // NOLINT(runtime/int) if (_BitScanReverse(&result, n)) { - return 31 - result; + return (int)(31 - result); } return 32; #elif defined(__GNUC__) @@ -359,7 +359,7 @@ PHMAP_BASE_INTERNAL_FORCEINLINE int CountTrailingZerosNonZero64(uint64_t n) { #if defined(_MSC_VER) && defined(_M_X64) unsigned long result = 0; // NOLINT(runtime/int) _BitScanForward64(&result, n); - return result; + return (int)result; #elif defined(_MSC_VER) unsigned long result = 0; // NOLINT(runtime/int) if (static_cast(n) == 0) { @@ -392,7 +392,7 @@ PHMAP_BASE_INTERNAL_FORCEINLINE int CountTrailingZerosNonZero32(uint32_t n) { #if defined(_MSC_VER) unsigned long result = 0; // NOLINT(runtime/int) _BitScanForward(&result, n); - return result; + return (int)result; #elif defined(__GNUC__) static_assert(sizeof(int) == sizeof(n), "__builtin_ctz does not take 32-bit arg"); diff --git a/parallel_hashmap/phmap_config.h b/parallel_hashmap/phmap_config.h index d462997..49a14ce 100644 --- a/parallel_hashmap/phmap_config.h +++ b/parallel_hashmap/phmap_config.h @@ -627,6 +627,15 @@ #endif +// ---------------------------------------------------------------------- +// constexpr if +// ---------------------------------------------------------------------- +#if __cplusplus >= 201703 || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703) + #define PHMAP_IF_CONSTEXPR(expr) if constexpr ((expr)) +#else + #define PHMAP_IF_CONSTEXPR(expr) if ((expr)) +#endif + // ---------------------------------------------------------------------- // base/macros.h // ---------------------------------------------------------------------- diff --git a/tests/btree_test.cc b/tests/btree_test.cc index b69578e..858c6df 100644 --- a/tests/btree_test.cc +++ b/tests/btree_test.cc @@ -1412,7 +1412,7 @@ namespace { EXPECT_EQ(BtreeNodePeer::GetNumValuesPerNode(), 3); EXPECT_EQ(BtreeNodePeer::GetNumValuesPerNode(), 61); EXPECT_EQ(BtreeNodePeer::GetNumValuesPerNode(), 100); - if (sizeof(void *) == 8) { + PHMAP_IF_CONSTEXPR (sizeof(void *) == 8) { EXPECT_EQ(BtreeNodePeer::GetNumValuesPerNode>(), BtreeNodePeer::GetNumValuesPerNode()); } @@ -1467,7 +1467,7 @@ namespace { EXPECT_EQ(BtreeNodePeer::GetNumValuesPerNode(), 3); EXPECT_EQ(BtreeNodePeer::GetNumValuesPerNode(), 61); EXPECT_EQ(BtreeNodePeer::GetNumValuesPerNode(), 100); - if (sizeof(void *) == 8) { + PHMAP_IF_CONSTEXPR (sizeof(void *) == 8) { EXPECT_EQ(BtreeNodePeer::GetNumValuesPerNode>(), BtreeNodePeer::GetNumValuesPerNode()); }