1 // -*- C++ -*- 2 //===----------------------------------------------------------------------===// 3 // 4 // The LLVM Compiler Infrastructure 5 // 6 // This file is dual licensed under the MIT and the University of Illinois Open 7 // Source Licenses. See LICENSE.TXT for details. 8 // 9 //===----------------------------------------------------------------------===// 10 11 // UNSUPPORTED: c++98, c++03, c++11, c++14 12 13 // <variant> 14 15 // template <class... Types> struct hash<variant<Types...>>; 16 // template <> struct hash<monostate>; 17 18 #include <cassert> 19 #include <type_traits> 20 #include <variant> 21 22 #include "test_macros.h" 23 #include "variant_test_helpers.hpp" 24 #include "poisoned_hash_helper.hpp" 25 26 #ifndef TEST_HAS_NO_EXCEPTIONS 27 namespace std { 28 template <> struct hash<::MakeEmptyT> { 29 size_t operator()(const ::MakeEmptyT &) const { 30 assert(false); 31 return 0; 32 } 33 }; 34 } 35 #endif 36 37 void test_hash_variant() { 38 { 39 using V = std::variant<int, long, int>; 40 using H = std::hash<V>; 41 const V v(std::in_place_index<0>, 42); 42 const V v_copy = v; 43 V v2(std::in_place_index<0>, 100); 44 const H h{}; 45 assert(h(v) == h(v)); 46 assert(h(v) != h(v2)); 47 assert(h(v) == h(v_copy)); 48 { 49 ASSERT_SAME_TYPE(decltype(h(v)), std::size_t); 50 static_assert(std::is_copy_constructible<H>::value, ""); 51 } 52 } 53 { 54 using V = std::variant<std::monostate, int, long, const char *>; 55 using H = std::hash<V>; 56 const char *str = "hello"; 57 const V v0; 58 const V v0_other; 59 const V v1(42); 60 const V v1_other(100); 61 V v2(100l); 62 V v2_other(999l); 63 V v3(str); 64 V v3_other("not hello"); 65 const H h{}; 66 assert(h(v0) == h(v0)); 67 assert(h(v0) == h(v0_other)); 68 assert(h(v1) == h(v1)); 69 assert(h(v1) != h(v1_other)); 70 assert(h(v2) == h(v2)); 71 assert(h(v2) != h(v2_other)); 72 assert(h(v3) == h(v3)); 73 assert(h(v3) != h(v3_other)); 74 assert(h(v0) != h(v1)); 75 assert(h(v0) != h(v2)); 76 assert(h(v0) != h(v3)); 77 assert(h(v1) != h(v2)); 78 assert(h(v1) != h(v3)); 79 assert(h(v2) != h(v3)); 80 } 81 #ifndef TEST_HAS_NO_EXCEPTIONS 82 { 83 using V = std::variant<int, MakeEmptyT>; 84 using H = std::hash<V>; 85 V v; 86 makeEmpty(v); 87 V v2; 88 makeEmpty(v2); 89 const H h{}; 90 assert(h(v) == h(v2)); 91 } 92 #endif 93 } 94 95 void test_hash_monostate() { 96 using H = std::hash<std::monostate>; 97 const H h{}; 98 std::monostate m1{}; 99 const std::monostate m2{}; 100 assert(h(m1) == h(m1)); 101 assert(h(m2) == h(m2)); 102 assert(h(m1) == h(m2)); 103 { 104 ASSERT_SAME_TYPE(decltype(h(m1)), std::size_t); 105 static_assert(std::is_copy_constructible<H>::value, ""); 106 } 107 { 108 test_hash_enabled_for_type<std::monostate>(); 109 } 110 } 111 112 void test_hash_variant_duplicate_elements() { 113 // Test that the index of the alternative participates in the hash value. 114 using V = std::variant<std::monostate, std::monostate>; 115 using H = std::hash<V>; 116 H h{}; 117 const V v1(std::in_place_index<0>); 118 const V v2(std::in_place_index<1>); 119 assert(h(v1) == h(v1)); 120 assert(h(v2) == h(v2)); 121 LIBCPP_ASSERT(h(v1) != h(v2)); 122 } 123 124 struct A {}; 125 struct B {}; 126 127 template <> 128 struct std::hash<B> { 129 size_t operator()(B const&) const { 130 return 0; 131 } 132 }; 133 134 void test_hash_variant_enabled() { 135 { 136 test_hash_enabled_for_type<std::variant<int> >(); 137 test_hash_enabled_for_type<std::variant<int*, long, double, const int> >(); 138 } 139 { 140 test_hash_disabled_for_type<std::variant<int, A>>(); 141 test_hash_disabled_for_type<std::variant<const A, void*>>(); 142 } 143 { 144 test_hash_enabled_for_type<std::variant<int, B>>(); 145 test_hash_enabled_for_type<std::variant<const B, int>>(); 146 } 147 } 148 149 int main() { 150 test_hash_variant(); 151 test_hash_variant_duplicate_elements(); 152 test_hash_monostate(); 153 test_hash_variant_enabled(); 154 } 155