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 // UNSUPPORTED: c++98, c++03, c++11, c++14
10 
11 #include <unordered_set>
12 #include <unordered_map>
13 #include <set>
14 #include <map>
15 #include "min_allocator.h"
16 
17 using namespace std;
18 
19 // [container.node.overview] Table 83.
20 template <class K, class T, class C1, class C2, class H1, class H2, class E1, class E2, class A_set, class A_map>
21 struct node_compatibility_table
22 {
23     static constexpr bool value =
24         is_same_v<typename map<K, T, C1, A_map>::node_type,               typename map<K, T, C2, A_map>::node_type> &&
25         is_same_v<typename map<K, T, C1, A_map>::node_type,               typename multimap<K, T, C2, A_map>::node_type> &&
26         is_same_v<typename set<K, C1, A_set>::node_type,                  typename set<K, C2, A_set>::node_type> &&
27         is_same_v<typename set<K, C1, A_set>::node_type,                  typename multiset<K, C2, A_set>::node_type> &&
28         is_same_v<typename unordered_map<K, T, H1, E1, A_map>::node_type, typename unordered_map<K, T, H2, E2, A_map>::node_type> &&
29         is_same_v<typename unordered_map<K, T, H1, E1, A_map>::node_type, typename unordered_multimap<K, T, H2, E2, A_map>::node_type> &&
30         is_same_v<typename unordered_set<K, H1, E1, A_set>::node_type,    typename unordered_set<K, H2, E2, A_set>::node_type> &&
31         is_same_v<typename unordered_set<K, H1, E1, A_set>::node_type,    typename unordered_multiset<K, H2, E2, A_set>::node_type>;
32 };
33 
34 template <class T> struct my_hash
35 {
36     using argument_type = T;
37     using result_type = size_t;
38     my_hash() = default;
39     size_t operator()(const T&) const {return 0;}
40 };
41 
42 template <class T> struct my_compare
43 {
44     my_compare() = default;
45     bool operator()(const T&, const T&) const {return true;}
46 };
47 
48 template <class T> struct my_equal
49 {
50     my_equal() = default;
51     bool operator()(const T&, const T&) const {return true;}
52 };
53 
54 struct Static
55 {
56     Static() = default;
57     Static(const Static&) = delete;
58     Static(Static&&) = delete;
59     Static& operator=(const Static&) = delete;
60     Static& operator=(Static&&) = delete;
61 };
62 
63 namespace std
64 {
65 template <> struct hash<Static>
66 {
67     using argument_type = Static;
68     using result_type = size_t;
69     hash() = default;
70     size_t operator()(const Static&) const;
71 };
72 }
73 
74 static_assert(node_compatibility_table<
75                   int, int, std::less<int>, std::less<int>, std::hash<int>,
76                   std::hash<int>, std::equal_to<int>, std::equal_to<int>,
77                   std::allocator<int>,
78                   std::allocator<std::pair<const int, int>>>::value,
79               "");
80 
81 static_assert(
82     node_compatibility_table<int, int, std::less<int>, my_compare<int>,
83                              std::hash<int>, my_hash<int>, std::equal_to<int>,
84                              my_equal<int>, allocator<int>,
85                              allocator<std::pair<const int, int>>>::value,
86     "");
87 
88 static_assert(node_compatibility_table<
89                   Static, int, my_compare<Static>, std::less<Static>,
90                   my_hash<Static>, std::hash<Static>, my_equal<Static>,
91                   std::equal_to<Static>, min_allocator<Static>,
92                   min_allocator<std::pair<const Static, int>>>::value,
93               "");
94 
95 template <class Container>
96 void test_node_handle_operations()
97 {
98     Container c;
99 
100     typename Container::node_type nt1, nt2 = c.extract(c.emplace().first);
101     assert(nt2.get_allocator() == c.get_allocator());
102     assert(!nt2.empty());
103     assert(nt1.empty());
104     std::swap(nt1, nt2);
105     assert(nt1.get_allocator() == c.get_allocator());
106     assert(nt2.empty());
107 }
108 
109 template <class Container>
110 void test_node_handle_operations_multi()
111 {
112     Container c;
113 
114     typename Container::node_type nt1, nt2 = c.extract(c.emplace());
115     assert(nt2.get_allocator() == c.get_allocator());
116     assert(!nt2.empty());
117     assert(nt1.empty());
118     std::swap(nt1, nt2);
119     assert(nt1.get_allocator() == c.get_allocator());
120     assert(nt2.empty());
121 }
122 
123 template <class> void test_typedef() {}
124 
125 template <class Container>
126 void test_insert_return_type()
127 {
128     test_typedef<typename Container::insert_return_type>();
129 }
130 
131 int main(int, char**)
132 {
133     test_node_handle_operations<std::map<int, int>>();
134     test_node_handle_operations_multi<std::multimap<int, int>>();
135     test_node_handle_operations<std::set<int>>();
136     test_node_handle_operations_multi<std::multiset<int>>();
137     test_node_handle_operations<std::unordered_map<int, int>>();
138     test_node_handle_operations_multi<std::unordered_multimap<int, int>>();
139     test_node_handle_operations<std::unordered_set<int>>();
140     test_node_handle_operations_multi<std::unordered_multiset<int>>();
141 
142     test_insert_return_type<std::map<int, int>>();
143     test_insert_return_type<std::set<int>>();
144     test_insert_return_type<std::unordered_map<int, int>>();
145     test_insert_return_type<std::unordered_set<int>>();
146 
147   return 0;
148 }
149