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