xref: /llvm-project/libcxx/test/support/test_transparent_unordered.h (revision d5db71d19f11d7c31257066aea6bd41ef04f28b7)
1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef TEST_TRANSPARENT_UNORDERED_H
10 #define TEST_TRANSPARENT_UNORDERED_H
11 
12 #include "test_macros.h"
13 #include "is_transparent.h"
14 
15 #include <cassert>
16 
17 #if TEST_STD_VER > 17
18 
19 template <typename T>
20 struct StoredType;
21 
22 template <typename T>
23 struct SearchedType;
24 
25 struct hash_impl {
26   template <typename T>
operatorhash_impl27   constexpr std::size_t operator()(SearchedType<T> const& t) const {
28     return static_cast<std::size_t>(t.get_value());
29   }
30 
31   template <typename T>
operatorhash_impl32   constexpr std::size_t operator()(StoredType<T> const& t) const {
33     return static_cast<std::size_t>(t.get_value());
34   }
35 };
36 
37 struct non_transparent_hash : hash_impl {};
38 
39 struct transparent_hash : hash_impl {
40   using is_transparent = void;
41 };
42 
43 struct transparent_hash_final final : transparent_hash {};
44 
45 struct transparent_equal_final final : std::equal_to<> {};
46 
47 template <typename T>
48 struct SearchedType {
SearchedTypeSearchedType49   explicit SearchedType(T value, int *counter) : value_(value), conversions_(counter) { }
50 
51   // Whenever a conversion is performed, increment the counter to keep track
52   // of conversions.
53   operator StoredType<T>() const {
54     ++*conversions_;
55     return StoredType<T>{value_};
56   }
57 
get_valueSearchedType58   int get_value() const {
59     return value_;
60   }
61 
62 private:
63   T value_;
64   int *conversions_;
65 };
66 
67 template <typename T>
68 struct StoredType {
69   StoredType() = default;
StoredTypeStoredType70   StoredType(T value) : value_(value) { }
71 
72   friend bool operator==(StoredType const& lhs, StoredType const& rhs) {
73     return lhs.value_ == rhs.value_;
74   }
75 
76   // If we're being passed a SearchedType<T> object, avoid the conversion
77   // to T. This allows testing that the transparent operations are correctly
78   // forwarding the SearchedType all the way to this comparison by checking
79   // that we didn't have a conversion when we search for a SearchedType<T>
80   // in a container full of StoredType<T>.
81   friend bool operator==(StoredType const& lhs, SearchedType<T> const& rhs) {
82     return lhs.value_ == rhs.get_value();
83   }
84 
get_valueStoredType85   int get_value() const {
86     return value_;
87   }
88 
89 private:
90   T value_;
91 };
92 
93 template<template<class...> class UnorderedSet, class Hash, class Equal>
94 using unord_set_type = UnorderedSet<StoredType<int>, Hash, Equal>;
95 
96 template<template<class...> class UnorderedMap, class Hash, class Equal>
97 using unord_map_type = UnorderedMap<StoredType<int>, int, Hash, Equal>;
98 
99 template<class Container>
test_transparent_find(Container c)100 void test_transparent_find(Container c) {
101   int conversions = 0;
102   assert(c.find(SearchedType<int>(1, &conversions)) != c.end());
103   assert(c.find(SearchedType<int>(2, &conversions)) != c.end());
104   assert(c.find(SearchedType<int>(3, &conversions)) == c.end());
105   assert(conversions == 0);
106 }
107 
108 template<class Container>
test_non_transparent_find(Container c)109 void test_non_transparent_find(Container c) {
110   int conversions = 0;
111   assert(c.find(SearchedType<int>(1, &conversions)) != c.end());
112   assert(conversions == 1);
113   assert(c.find(SearchedType<int>(2, &conversions)) != c.end());
114   assert(conversions == 2);
115   assert(c.find(SearchedType<int>(3, &conversions)) == c.end());
116   assert(conversions == 3);
117 }
118 
119 template<class Container>
test_transparent_count(Container c)120 void test_transparent_count(Container c) {
121   int conversions = 0;
122   assert(c.count(SearchedType<int>(1, &conversions)) > 0);
123   assert(c.count(SearchedType<int>(2, &conversions)) > 0);
124   assert(c.count(SearchedType<int>(3, &conversions)) == 0);
125   assert(conversions == 0);
126 }
127 
128 template<class Container>
test_non_transparent_count(Container c)129 void test_non_transparent_count(Container c) {
130   int conversions = 0;
131   assert(c.count(SearchedType<int>(1, &conversions)) > 0);
132   assert(conversions == 1);
133   assert(c.count(SearchedType<int>(2, &conversions)) > 0);
134   assert(conversions == 2);
135   assert(c.count(SearchedType<int>(3, &conversions)) == 0);
136   assert(conversions == 3);
137 }
138 
139 template<class Container>
test_transparent_contains(Container c)140 void test_transparent_contains(Container c) {
141   int conversions = 0;
142   assert(c.contains(SearchedType<int>(1, &conversions)));
143   assert(c.contains(SearchedType<int>(2, &conversions)));
144   assert(!c.contains(SearchedType<int>(3, &conversions)));
145   assert(conversions == 0);
146 }
147 
148 template<class Container>
test_non_transparent_contains(Container c)149 void test_non_transparent_contains(Container c) {
150   int conversions = 0;
151   assert(c.contains(SearchedType<int>(1, &conversions)));
152   assert(conversions == 1);
153   assert(c.contains(SearchedType<int>(2, &conversions)));
154   assert(conversions == 2);
155   assert(!c.contains(SearchedType<int>(3, &conversions)));
156   assert(conversions == 3);
157 }
158 
159 template<class Container>
test_transparent_equal_range(Container c)160 void test_transparent_equal_range(Container c) {
161   int conversions = 0;
162   auto iters = c.equal_range(SearchedType<int>(1, &conversions));
163   assert(std::distance(iters.first, iters.second) > 0);
164   iters = c.equal_range(SearchedType<int>(2, &conversions));
165   assert(std::distance(iters.first, iters.second) > 0);
166   iters = c.equal_range(SearchedType<int>(3, &conversions));
167   assert(std::distance(iters.first, iters.second) == 0);
168   assert(conversions == 0);
169 }
170 
171 template<class Container>
test_non_transparent_equal_range(Container c)172 void test_non_transparent_equal_range(Container c) {
173   int conversions = 0;
174   auto iters = c.equal_range(SearchedType<int>(1, &conversions));
175   assert(std::distance(iters.first, iters.second) > 0);
176   assert(conversions == 1);
177   iters = c.equal_range(SearchedType<int>(2, &conversions));
178   assert(std::distance(iters.first, iters.second) > 0);
179   assert(conversions == 2);
180   iters = c.equal_range(SearchedType<int>(3, &conversions));
181   assert(std::distance(iters.first, iters.second) == 0);
182   assert(conversions == 3);
183 }
184 
185 #endif // TEST_STD_VER > 17
186 
187 #endif // TEST_TRANSPARENT_UNORDERED_H
188