| //===----------------------------------------------------------------------===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| |
| // <unordered_set> |
| |
| // template <class Key, class T, class Hash, class Pred, class Alloc> |
| // bool |
| // operator==(const unordered_multiset<Key, T, Hash, Pred, Alloc>& x, |
| // const unordered_multiset<Key, T, Hash, Pred, Alloc>& y); |
| // |
| // template <class Key, class T, class Hash, class Pred, class Alloc> |
| // bool |
| // operator!=(const unordered_multiset<Key, T, Hash, Pred, Alloc>& x, |
| // const unordered_multiset<Key, T, Hash, Pred, Alloc>& y); |
| |
| // Implements paper: http://wg21.link/p0809 |
| |
| #include <cassert> |
| #include <cstddef> |
| #include <functional> |
| #include <limits> |
| #include <unordered_set> |
| |
| template <class T> |
| std::size_t hash_identity(T val) { |
| return val; |
| } |
| template <class T> |
| std::size_t hash_neg(T val) { |
| return std::numeric_limits<T>::max() - val; |
| } |
| template <class T> |
| std::size_t hash_scale(T val) { |
| return static_cast<std::size_t>(val << 1); |
| } |
| template <class T> |
| std::size_t hash_even(T val) { |
| return val & 1 ? 1 : 0; |
| } |
| template <class T> |
| std::size_t hash_same(T /*val*/) { |
| return 1; |
| } |
| |
| template <class T> |
| std::size_t hash_identity(T* val) { |
| return *val; |
| } |
| template <class T> |
| std::size_t hash_neg(T* val) { |
| return std::numeric_limits<T>::max() - *val; |
| } |
| template <class T> |
| std::size_t hash_scale(T* val) { |
| return static_cast<std::size_t>(*val << 1); |
| } |
| template <class T> |
| std::size_t hash_even(T* val) { |
| return *val & 1 ? 1 : 0; |
| } |
| |
| template <class T, std::size_t N> |
| void test(T (&vals)[N]) { |
| using Hash = std::size_t (*)(T); |
| using C = std::unordered_multiset<T, Hash, std::equal_to<T> >; |
| |
| C c1(std::begin(vals), std::end(vals), 0, hash_identity); |
| C c2(std::begin(vals), std::end(vals), 0, hash_neg); |
| C c3(std::begin(vals), std::end(vals), 0, hash_scale); |
| C c4(std::begin(vals), std::end(vals), 0, hash_even); |
| C c5(std::begin(vals), std::end(vals), 0, hash_same); |
| |
| assert(c1 == c1); |
| assert(c1 == c2); |
| assert(c1 == c3); |
| assert(c1 == c4); |
| assert(c1 == c5); |
| |
| assert(c2 == c1); |
| assert(c2 == c2); |
| assert(c2 == c3); |
| assert(c2 == c4); |
| assert(c2 == c5); |
| |
| assert(c3 == c1); |
| assert(c3 == c2); |
| assert(c3 == c3); |
| assert(c3 == c4); |
| assert(c3 == c5); |
| |
| assert(c4 == c1); |
| assert(c4 == c2); |
| assert(c4 == c3); |
| assert(c4 == c4); |
| assert(c4 == c5); |
| |
| assert(c5 == c1); |
| assert(c5 == c2); |
| assert(c5 == c3); |
| assert(c5 == c4); |
| assert(c5 == c5); |
| } |
| |
| int main(int, char**) { |
| { |
| std::size_t vals[] = { |
| // clang-format off |
| 1, |
| 2, 2, |
| 3, 3, 3, |
| 4, 4, 4, 4, |
| 5, 5, 5, 5, 5, |
| 6, 6, 6, 6, 6, 6, |
| 7, 7, 7, 7, 7, 7, 7, |
| 8, 8, 8, 8, 8, 8, 8, 8, |
| 9, 9, 9, 9, 9, 9, 9, 9, 9, |
| 10 |
| // clang-format on |
| }; |
| test(vals); |
| } |
| { |
| bool vals[] = {true, false}; |
| test(vals); |
| } |
| { |
| char* vals[] = {(char*)("a"), (char*)("b"), (char*)("cde")}; |
| test(vals); |
| } |
| |
| return 0; |
| } |