llvm.org GIT mirror llvm / 4d628e2
We really want to hash pairs of directly-hashable data as directly hashable data. This matters when we have pair<T*, U*> as a key, which is quite common in DenseMap, etc. To that end, we need to detect when this is safe. The requirements on a generic std::pair<T, U> are: 1) Both T and U must satisfy the existing is_hashable_data trait. Note that this includes the requirement that T and U have no internal padding bits or other bits not contributing directly to equality. 2) The alignment constraints of std::pair<T, U> do not require padding between consecutive objects. 3) The alignment constraints of U and the size of T do not conspire to require padding between the first and second elements. Grow two somewhat magical traits to detect this by forming a pod structure and inspecting offset artifacts on it. Hopefully this won't cause any compilers to panic. Added and adjusted tests now that pairs, even nested pairs, are treated as just sequences of data. Thanks to Jeffrey Yasskin for helping me sort through this and reviewing the somewhat subtle traits. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@151883 91177308-0d34-0410-b5e6-96231b3b80d8 Chandler Carruth 8 years ago
3 changed file(s) with 35 addition(s) and 5 deletion(s). Raw diff Collapse all Expand all
349349 : integral_constant::value || is_pointer::value) &&
350350 64 % sizeof(T) == 0)> {};
351351
352 // Special case std::pair to detect when both types are viable and when there
353 // is no alignment-derived padding in the pair. This is a bit of a lie because
354 // std::pair isn't truly POD, but it's close enough in all reasonable
355 // implementations for our use case of hashing the underlying data.
356 template struct is_hashable_data >
357 : integral_constant::value &&
358 is_hashable_data::value &&
359 !is_alignment_padded >::value &&
360 !is_pod_pair_padded::value)> {};
361
352362 /// \brief Helper to get the hashable data representation for a type.
353363 /// This variant is enabled when the type itself can be used.
354364 template
124124 template struct is_pointer : false_type {};
125125 template struct is_pointer : true_type {};
126126
127 /// \brief Metafunction to compute whether a type requires alignment padding.
128 /// When true, an object of this type will have padding bytes inside its
129 /// 'sizeof' bytes.
130 template class is_alignment_padded {
131 struct pod_size_tester { T t; char c; };
132 public:
133 enum { value = offsetof(pod_size_tester, c) != sizeof(T) };
134 };
135
136 /// \brief Metafunction to determine whether an adjacent pair of two types will
137 /// require padding between them due to alignment.
138 template class is_pod_pair_padded {
139 struct pod_pair { T t; U u; };
140 struct pod_char_pair { T t; char c; };
141 public:
142 enum { value = offsetof(pod_pair, u) != offsetof(pod_char_pair, c) };
143 };
144
127145
128146 // enable_if_c - Enable/disable a template based on a metafunction
129147 template
6565 EXPECT_NE(hash_combine(42, 43), hash_value(std::make_pair(42ull, 43ull)));
6666 EXPECT_NE(hash_combine(42, 43), hash_value(std::make_pair(42, 43ull)));
6767 EXPECT_NE(hash_combine(42, 43), hash_value(std::make_pair(42ull, 43)));
68 EXPECT_EQ(hash_combine(42, hash_combine(43, hash_combine(44, 45))),
69 hash_value(
70 std::make_pair(42, std::make_pair(43, std::make_pair(44, 45)))));
71 EXPECT_EQ(hash_combine(42, 43), hash_value(std::make_pair(42, 43)));
72 EXPECT_EQ(hash_combine(42, 43), hash_value(std::make_pair(42, 43)));
68
69 // Note that pairs are implicitly flattened to a direct sequence of data and
70 // hashed efficiently as a consequence.
71 EXPECT_EQ(hash_combine(42, 43, 44),
72 hash_value(std::make_pair(42, std::make_pair(43, 44))));
73 EXPECT_EQ(hash_value(std::make_pair(42, std::make_pair(43, 44))),
74 hash_value(std::make_pair(std::make_pair(42, 43), 44)));
7375 }
7476
7577 template T *begin(T (&arr)[N]) { return arr; }