1 //===----------------------------------------------------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is dual licensed under the MIT and the University of Illinois Open 6 // Source Licenses. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // UNSUPPORTED: c++98, c++03, c++11, c++14 11 12 // <unordered_map> 13 14 // class unordered_map 15 16 // template <class M> 17 // pair<iterator, bool> insert_or_assign(const key_type& k, M&& obj); // C++17 18 // template <class M> 19 // pair<iterator, bool> insert_or_assign(key_type&& k, M&& obj); // C++17 20 // template <class M> 21 // iterator insert_or_assign(const_iterator hint, const key_type& k, M&& obj); // C++17 22 // template <class M> 23 // iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj); // C++17 24 25 #include <unordered_map> 26 #include <cassert> 27 #include <tuple> 28 29 30 class Moveable 31 { 32 Moveable(const Moveable&); 33 Moveable& operator=(const Moveable&); 34 35 int int_; 36 double double_; 37 public: 38 Moveable() : int_(0), double_(0) {} 39 Moveable(int i, double d) : int_(i), double_(d) {} 40 Moveable(Moveable&& x) 41 : int_(x.int_), double_(x.double_) 42 {x.int_ = -1; x.double_ = -1;} 43 Moveable& operator=(Moveable&& x) 44 {int_ = x.int_; x.int_ = -1; 45 double_ = x.double_; x.double_ = -1; 46 return *this; 47 } 48 49 bool operator==(const Moveable& x) const 50 {return int_ == x.int_ && double_ == x.double_;} 51 bool operator<(const Moveable& x) const 52 {return int_ < x.int_ || (int_ == x.int_ && double_ < x.double_);} 53 size_t hash () const { return std::hash<int>()(int_) + std::hash<double>()(double_); } 54 55 int get() const {return int_;} 56 bool moved() const {return int_ == -1;} 57 }; 58 59 namespace std { 60 template <> struct hash<Moveable> { 61 size_t operator () (const Moveable &m) const { return m.hash(); } 62 }; 63 } 64 65 int main() 66 { 67 68 { // pair<iterator, bool> insert_or_assign(const key_type& k, M&& obj); 69 typedef std::unordered_map<int, Moveable> M; 70 typedef std::pair<M::iterator, bool> R; 71 M m; 72 R r; 73 for (int i = 0; i < 20; i += 2) 74 m.emplace ( i, Moveable(i, (double) i)); 75 assert(m.size() == 10); 76 77 for (int i=0; i < 20; i += 2) 78 { 79 Moveable mv(i+1, i+1); 80 r = m.insert_or_assign(i, std::move(mv)); 81 assert(m.size() == 10); 82 assert(!r.second); // was not inserted 83 assert(mv.moved()); // was moved from 84 assert(r.first->first == i); // key 85 assert(r.first->second.get() == i+1); // value 86 } 87 88 Moveable mv1(5, 5.0); 89 r = m.insert_or_assign(-1, std::move(mv1)); 90 assert(m.size() == 11); 91 assert(r.second); // was inserted 92 assert(mv1.moved()); // was moved from 93 assert(r.first->first == -1); // key 94 assert(r.first->second.get() == 5); // value 95 96 Moveable mv2(9, 9.0); 97 r = m.insert_or_assign(3, std::move(mv2)); 98 assert(m.size() == 12); 99 assert(r.second); // was inserted 100 assert(mv2.moved()); // was moved from 101 assert(r.first->first == 3); // key 102 assert(r.first->second.get() == 9); // value 103 104 Moveable mv3(-1, 5.0); 105 r = m.insert_or_assign(117, std::move(mv3)); 106 assert(m.size() == 13); 107 assert(r.second); // was inserted 108 assert(mv3.moved()); // was moved from 109 assert(r.first->first == 117); // key 110 assert(r.first->second.get() == -1); // value 111 } 112 { // pair<iterator, bool> insert_or_assign(key_type&& k, M&& obj); 113 typedef std::unordered_map<Moveable, Moveable> M; 114 typedef std::pair<M::iterator, bool> R; 115 M m; 116 R r; 117 for (int i = 0; i < 20; i += 2) 118 m.emplace ( Moveable(i, (double) i), Moveable(i+1, (double) i+1)); 119 assert(m.size() == 10); 120 121 Moveable mvkey1(2, 2.0); 122 Moveable mv1(4, 4.0); 123 r = m.insert_or_assign(std::move(mvkey1), std::move(mv1)); 124 assert(m.size() == 10); 125 assert(!r.second); // was not inserted 126 assert(!mvkey1.moved()); // was not moved from 127 assert(mv1.moved()); // was moved from 128 assert(r.first->first == mvkey1); // key 129 assert(r.first->second.get() == 4); // value 130 131 Moveable mvkey2(3, 3.0); 132 Moveable mv2(5, 5.0); 133 r = m.try_emplace(std::move(mvkey2), std::move(mv2)); 134 assert(m.size() == 11); 135 assert(r.second); // was inserted 136 assert(mv2.moved()); // was moved from 137 assert(mvkey2.moved()); // was moved from 138 assert(r.first->first.get() == 3); // key 139 assert(r.first->second.get() == 5); // value 140 } 141 { // iterator insert_or_assign(const_iterator hint, const key_type& k, M&& obj); 142 typedef std::unordered_map<int, Moveable> M; 143 M m; 144 M::iterator r; 145 for (int i = 0; i < 20; i += 2) 146 m.emplace ( i, Moveable(i, (double) i)); 147 assert(m.size() == 10); 148 M::const_iterator it = m.find(2); 149 150 Moveable mv1(3, 3.0); 151 r = m.insert_or_assign(it, 2, std::move(mv1)); 152 assert(m.size() == 10); 153 assert(mv1.moved()); // was moved from 154 assert(r->first == 2); // key 155 assert(r->second.get() == 3); // value 156 157 Moveable mv2(5, 5.0); 158 r = m.insert_or_assign(it, 3, std::move(mv2)); 159 assert(m.size() == 11); 160 assert(mv2.moved()); // was moved from 161 assert(r->first == 3); // key 162 assert(r->second.get() == 5); // value 163 } 164 { // iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj); 165 typedef std::unordered_map<Moveable, Moveable> M; 166 M m; 167 M::iterator r; 168 for (int i = 0; i < 20; i += 2) 169 m.emplace ( Moveable(i, (double) i), Moveable(i+1, (double) i+1)); 170 assert(m.size() == 10); 171 M::const_iterator it = std::next(m.cbegin()); 172 173 Moveable mvkey1(2, 2.0); 174 Moveable mv1(4, 4.0); 175 r = m.insert_or_assign(it, std::move(mvkey1), std::move(mv1)); 176 assert(m.size() == 10); 177 assert(mv1.moved()); // was moved from 178 assert(!mvkey1.moved()); // was not moved from 179 assert(r->first == mvkey1); // key 180 assert(r->second.get() == 4); // value 181 182 Moveable mvkey2(3, 3.0); 183 Moveable mv2(5, 5.0); 184 r = m.insert_or_assign(it, std::move(mvkey2), std::move(mv2)); 185 assert(m.size() == 11); 186 assert(mv2.moved()); // was moved from 187 assert(mvkey2.moved()); // was moved from 188 assert(r->first.get() == 3); // key 189 assert(r->second.get() == 5); // value 190 } 191 192 }