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++03, c++11, c++14 11 12 // <map> 13 14 // class 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 <__config> 26 #include <map> 27 #include <cassert> 28 #include <tuple> 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 54 int get() const {return int_;} 55 bool moved() const {return int_ == -1;} 56 }; 57 58 59 int main() 60 { 61 #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES 62 #ifndef _LIBCPP_HAS_NO_VARIADICS 63 64 { // pair<iterator, bool> try_emplace(const key_type& k, Args&&... args); 65 typedef std::map<int, Moveable> M; 66 typedef std::pair<M::iterator, bool> R; 67 M m; 68 R r; 69 for (int i = 0; i < 20; i += 2) 70 m.emplace (i, Moveable(i, (double) i)); 71 assert(m.size() == 10); 72 73 Moveable mv1(3, 3.0); 74 for (int i=0; i < 20; i += 2) 75 { 76 r = m.try_emplace(i, std::move(mv1)); 77 assert(m.size() == 10); 78 assert(!r.second); // was not inserted 79 assert(!mv1.moved()); // was not moved from 80 assert(r.first->first == i); // key 81 } 82 83 r = m.try_emplace(-1, std::move(mv1)); 84 assert(m.size() == 11); 85 assert(r.second); // was inserted 86 assert(mv1.moved()); // was moved from 87 assert(r.first->first == -1); // key 88 assert(r.first->second.get() == 3); // value 89 90 Moveable mv2(5, 3.0); 91 r = m.try_emplace(5, std::move(mv2)); 92 assert(m.size() == 12); 93 assert(r.second); // was inserted 94 assert(mv2.moved()); // was moved from 95 assert(r.first->first == 5); // key 96 assert(r.first->second.get() == 5); // value 97 98 Moveable mv3(-1, 3.0); 99 r = m.try_emplace(117, std::move(mv2)); 100 assert(m.size() == 13); 101 assert(r.second); // was inserted 102 assert(mv2.moved()); // was moved from 103 assert(r.first->first == 117); // key 104 assert(r.first->second.get() == -1); // value 105 } 106 107 { // pair<iterator, bool> try_emplace(key_type&& k, Args&&... args); 108 typedef std::map<Moveable, Moveable> M; 109 typedef std::pair<M::iterator, bool> R; 110 M m; 111 R r; 112 for ( int i = 0; i < 20; i += 2 ) 113 m.emplace ( Moveable(i, (double) i), Moveable(i+1, (double) i+1)); 114 assert(m.size() == 10); 115 116 Moveable mvkey1(2, 2.0); 117 Moveable mv1(4, 4.0); 118 r = m.try_emplace(std::move(mvkey1), std::move(mv1)); 119 assert(m.size() == 10); 120 assert(!r.second); // was not inserted 121 assert(!mv1.moved()); // was not moved from 122 assert(!mvkey1.moved()); // was not moved from 123 assert(r.first->first == mvkey1); // key 124 125 Moveable mvkey2(3, 3.0); 126 r = m.try_emplace(std::move(mvkey2), std::move(mv1)); 127 assert(m.size() == 11); 128 assert(r.second); // was inserted 129 assert(mv1.moved()); // was moved from 130 assert(mvkey2.moved()); // was moved from 131 assert(r.first->first.get() == 3); // key 132 assert(r.first->second.get() == 4); // value 133 } 134 135 { // iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args); 136 typedef std::map<int, Moveable> M; 137 M m; 138 M::iterator r; 139 for ( int i = 0; i < 20; i += 2 ) 140 m.try_emplace ( i, Moveable(i, (double) i)); 141 assert(m.size() == 10); 142 M::const_iterator it = m.find(2); 143 144 Moveable mv1(3, 3.0); 145 for (int i=0; i < 20; i += 2) 146 { 147 r = m.try_emplace(it, i, std::move(mv1)); 148 assert(m.size() == 10); 149 assert(!mv1.moved()); // was not moved from 150 assert(r->first == i); // key 151 assert(r->second.get() == i); // value 152 } 153 154 r = m.try_emplace(it, 3, std::move(mv1)); 155 assert(m.size() == 11); 156 assert(mv1.moved()); // was moved from 157 assert(r->first == 3); // key 158 assert(r->second.get() == 3); // value 159 } 160 161 { // iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args); 162 typedef std::map<Moveable, Moveable> M; 163 M m; 164 M::iterator r; 165 for ( int i = 0; i < 20; i += 2 ) 166 m.emplace ( Moveable(i, (double) i), Moveable(i+1, (double) i+1)); 167 assert(m.size() == 10); 168 M::const_iterator it = std::next(m.cbegin()); 169 170 Moveable mvkey1(2, 2.0); 171 Moveable mv1(4, 4.0); 172 r = m.try_emplace(it, std::move(mvkey1), std::move(mv1)); 173 assert(m.size() == 10); 174 assert(!mv1.moved()); // was not moved from 175 assert(!mvkey1.moved()); // was not moved from 176 assert(r->first == mvkey1); // key 177 178 Moveable mvkey2(3, 3.0); 179 r = m.try_emplace(it, std::move(mvkey2), std::move(mv1)); 180 assert(m.size() == 11); 181 assert(mv1.moved()); // was moved from 182 assert(mvkey2.moved()); // was moved from 183 assert(r->first.get() == 3); // key 184 assert(r->second.get() == 4); // value 185 } 186 187 #endif // _LIBCPP_HAS_NO_VARIADICS 188 #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES 189 } 190