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