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