Updated the diff with the changes from LWG#2464
http://reviews.llvm.org/D10669
Files:
include/map
test/std/containers/associative/map/map.modifiers/insert_or_assign.pass.cpp
test/std/containers/associative/map/map.modifiers/try.emplace.pass.cpp
EMAIL PREFERENCES
http://reviews.llvm.org/settings/panel/emailpreferences/
Index: include/map
===================================================================
--- include/map
+++ include/map
@@ -135,6 +135,23 @@
void insert(InputIterator first, InputIterator last);
void insert(initializer_list<value_type> il);
+ template <class... Args>
+ pair<iterator, bool> try_emplace(const key_type& k, Args&&... args); // C++17
+ template <class... Args>
+ pair<iterator, bool> try_emplace(key_type&& k, Args&&... args); // C++17
+ template <class... Args>
+ iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args); // C++17
+ template <class... Args>
+ iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args); // C++17
+ template <class M>
+ pair<iterator, bool> insert_or_assign(const key_type& k, M&& obj); // C++17
+ template <class M>
+ pair<iterator, bool> insert_or_assign(key_type&& k, M&& obj); // C++17
+ template <class M>
+ iterator insert_or_assign(const_iterator hint, const key_type& k, M&& obj); // C++17
+ template <class M>
+ iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj); // C++17
+
iterator erase(const_iterator position);
iterator erase(iterator position); // C++14
size_type erase(const key_type& k);
@@ -1077,6 +1094,120 @@
#endif // _LIBCPP_HAS_NO_GENERALIZED_INITIALIZERS
+#if _LIBCPP_STD_VER > 14
+#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
+#ifndef _LIBCPP_HAS_NO_VARIADICS
+ template <class... _Args>
+ _LIBCPP_INLINE_VISIBILITY
+ pair<iterator, bool> try_emplace(const key_type& __k, _Args&&... __args)
+ {
+ iterator __p = lower_bound(__k);
+ if ( __p != end() && !key_comp()(__k, __p->first))
+ return _VSTD::make_pair(__p, false);
+ else
+ return _VSTD::make_pair(
+ emplace_hint(__p,
+ _VSTD::piecewise_construct, _VSTD::forward_as_tuple(__k),
+ _VSTD::forward_as_tuple(_VSTD::forward<_Args>(__args)...)),
+ true);
+ }
+
+ template <class... _Args>
+ _LIBCPP_INLINE_VISIBILITY
+ pair<iterator, bool> try_emplace(key_type&& __k, _Args&&... __args)
+ {
+ iterator __p = lower_bound(__k);
+ if ( __p != end() && !key_comp()(__k, __p->first))
+ return _VSTD::make_pair(__p, false);
+ else
+ return _VSTD::make_pair(
+ emplace_hint(__p,
+ _VSTD::piecewise_construct, _VSTD::forward_as_tuple(_VSTD::move(__k)),
+ _VSTD::forward_as_tuple(_VSTD::forward<_Args>(__args)...)),
+ true);
+ }
+
+ template <class... _Args>
+ _LIBCPP_INLINE_VISIBILITY
+ iterator try_emplace(const_iterator __h, const key_type& __k, _Args&&... __args)
+ {
+ iterator __p = lower_bound(__k);
+ if ( __p != end() && !key_comp()(__k, __p->first))
+ return __p;
+ else
+ return emplace_hint(__p,
+ _VSTD::piecewise_construct, _VSTD::forward_as_tuple(__k),
+ _VSTD::forward_as_tuple(_VSTD::forward<_Args>(__args)...));
+ }
+
+ template <class... _Args>
+ _LIBCPP_INLINE_VISIBILITY
+ iterator try_emplace(const_iterator __h, key_type&& __k, _Args&&... __args)
+ {
+ iterator __p = lower_bound(__k);
+ if ( __p != end() && !key_comp()(__k, __p->first))
+ return __p;
+ else
+ return emplace_hint(__p,
+ _VSTD::piecewise_construct, _VSTD::forward_as_tuple(_VSTD::move(__k)),
+ _VSTD::forward_as_tuple(_VSTD::forward<_Args>(__args)...));
+ }
+
+ template <class _Vp>
+ _LIBCPP_INLINE_VISIBILITY
+ pair<iterator, bool> insert_or_assign(const key_type& __k, _Vp&& __v)
+ {
+ iterator __p = lower_bound(__k);
+ if ( __p != end() && !key_comp()(__k, __p->first))
+ {
+ __p->second = _VSTD::forward<_Vp>(__v);
+ return _VSTD::make_pair(__p, false);
+ }
+ return _VSTD::make_pair(emplace_hint(__p, __k, _VSTD::forward<_Vp>(__v)), true);
+ }
+
+ template <class _Vp>
+ _LIBCPP_INLINE_VISIBILITY
+ pair<iterator, bool> insert_or_assign(key_type&& __k, _Vp&& __v)
+ {
+ iterator __p = lower_bound(__k);
+ if ( __p != end() && !key_comp()(__k, __p->first))
+ {
+ __p->second = _VSTD::forward<_Vp>(__v);
+ return _VSTD::make_pair(__p, false);
+ }
+ return _VSTD::make_pair(emplace_hint(__p, _VSTD::move(__k), _VSTD::forward<_Vp>(__v)), true);
+ }
+
+ template <class _Vp>
+ _LIBCPP_INLINE_VISIBILITY
+ iterator insert_or_assign(const_iterator __h, const key_type& __k, _Vp&& __v)
+ {
+ iterator __p = lower_bound(__k);
+ if ( __p != end() && !key_comp()(__k, __p->first))
+ {
+ __p->second = _VSTD::forward<_Vp>(__v);
+ return __p;
+ }
+ return emplace_hint(__h, __k, _VSTD::forward<_Vp>(__v));
+ }
+
+ template <class _Vp>
+ _LIBCPP_INLINE_VISIBILITY
+ iterator insert_or_assign(const_iterator __h, key_type&& __k, _Vp&& __v)
+ {
+ iterator __p = lower_bound(__k);
+ if ( __p != end() && !key_comp()(__k, __p->first))
+ {
+ __p->second = _VSTD::forward<_Vp>(__v);
+ return __p;
+ }
+ return emplace_hint(__h, _VSTD::move(__k), _VSTD::forward<_Vp>(__v));
+ }
+#endif
+#endif
+#endif
+
_LIBCPP_INLINE_VISIBILITY
iterator erase(const_iterator __p) {return __tree_.erase(__p.__i_);}
_LIBCPP_INLINE_VISIBILITY
Index: test/std/containers/associative/map/map.modifiers/insert_or_assign.pass.cpp
===================================================================
--- test/std/containers/associative/map/map.modifiers/insert_or_assign.pass.cpp
+++ test/std/containers/associative/map/map.modifiers/insert_or_assign.pass.cpp
@@ -0,0 +1,173 @@
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// UNSUPPORTED: c++03, c++11, c++14
+
+// <map>
+
+// class map
+
+// template <class M>
+// pair<iterator, bool> insert_or_assign(const key_type& k, M&& obj); // C++17
+// template <class M>
+// pair<iterator, bool> insert_or_assign(key_type&& k, M&& obj); // C++17
+// template <class M>
+// iterator insert_or_assign(const_iterator hint, const key_type& k, M&& obj); // C++17
+// template <class M>
+// iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj); // C++17
+
+#include <__config>
+#include <map>
+#include <cassert>
+#include <tuple>
+
+#include <iostream>
+
+class Moveable
+{
+ Moveable(const Moveable&);
+ Moveable& operator=(const Moveable&);
+
+ int int_;
+ double double_;
+public:
+ Moveable() : int_(0), double_(0) {}
+ Moveable(int i, double d) : int_(i), double_(d) {}
+ Moveable(Moveable&& x)
+ : int_(x.int_), double_(x.double_)
+ {x.int_ = -1; x.double_ = -1;}
+ Moveable& operator=(Moveable&& x)
+ {int_ = x.int_; x.int_ = -1;
+ double_ = x.double_; x.double_ = -1;
+ return *this;
+ }
+
+ bool operator==(const Moveable& x) const
+ {return int_ == x.int_ && double_ == x.double_;}
+ bool operator<(const Moveable& x) const
+ {return int_ < x.int_ || (int_ == x.int_ && double_ < x.double_);}
+
+ int get() const {return int_;}
+ bool moved() const {return int_ == -1;}
+};
+
+
+int main()
+{
+#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
+#ifndef _LIBCPP_HAS_NO_VARIADICS
+
+ { // pair<iterator, bool> insert_or_assign(const key_type& k, M&& obj);
+ typedef std::map<int, Moveable> M;
+ typedef std::pair<M::iterator, bool> R;
+ M m;
+ R r;
+ for ( int i = 0; i < 20; i += 2 )
+ m.emplace ( i, Moveable(i, (double) i));
+ assert(m.size() == 10);
+
+ Moveable mv1(3, 3.0);
+ r = m.insert_or_assign(2, std::move(mv1));
+ assert(m.size() == 10);
+ assert(!r.second); // was not inserted
+ assert(mv1.moved()); // was moved from
+ assert(r.first->first == 2); // key
+ assert(r.first->second.get() == 3); // value
+
+ Moveable mv2(5, 5.0);
+ r = m.insert_or_assign(3, std::move(mv2));
+ assert(m.size() == 11);
+ assert(r.second); // was inserted
+ assert(mv2.moved()); // was moved from
+ assert(r.first->first == 3); // key
+ assert(r.first->second.get() == 5); // value
+ }
+ { // pair<iterator, bool> insert_or_assign(key_type&& k, M&& obj);
+ typedef std::map<Moveable, Moveable> M;
+ typedef std::pair<M::iterator, bool> R;
+ M m;
+ R r;
+ for ( int i = 0; i < 20; i += 2 )
+ m.emplace ( Moveable(i, (double) i), Moveable(i+1, (double) i+1));
+ assert(m.size() == 10);
+
+ Moveable mvkey1(2, 2.0);
+ Moveable mv1(4, 4.0);
+ r = m.insert_or_assign(std::move(mvkey1), std::move(mv1));
+ assert(m.size() == 10);
+ assert(!r.second); // was not inserted
+ assert(!mvkey1.moved()); // was not moved from
+ assert(mv1.moved()); // was moved from
+ assert(r.first->first == mvkey1); // key
+ assert(r.first->second.get() == 4); // value
+
+ Moveable mvkey2(3, 3.0);
+ Moveable mv2(5, 5.0);
+ r = m.try_emplace(std::move(mvkey2), std::move(mv2));
+ assert(m.size() == 11);
+ assert(r.second); // was inserted
+ assert(mv2.moved()); // was moved from
+ assert(mvkey2.moved()); // was moved from
+ assert(r.first->first.get() == 3); // key
+ assert(r.first->second.get() == 5); // value
+ }
+ { // iterator insert_or_assign(const_iterator hint, const key_type& k, M&& obj);
+ typedef std::map<int, Moveable> M;
+ M m;
+ M::iterator r;
+ for ( int i = 0; i < 20; i += 2 )
+ m.emplace ( i, Moveable(i, (double) i));
+ assert(m.size() == 10);
+ M::const_iterator it = m.find(2);
+
+ Moveable mv1(3, 3.0);
+ r = m.insert_or_assign(it, 2, std::move(mv1));
+ assert(m.size() == 10);
+ assert(mv1.moved()); // was moved from
+ assert(r->first == 2); // key
+ assert(r->second.get() == 3); // value
+
+ Moveable mv2(5, 5.0);
+ r = m.insert_or_assign(it, 3, std::move(mv2));
+ assert(m.size() == 11);
+ assert(mv2.moved()); // was moved from
+ assert(r->first == 3); // key
+ assert(r->second.get() == 5); // value
+ }
+ { // iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj);
+ typedef std::map<Moveable, Moveable> M;
+ M m;
+ M::iterator r;
+ for ( int i = 0; i < 20; i += 2 )
+ m.emplace ( Moveable(i, (double) i), Moveable(i+1, (double) i+1));
+ assert(m.size() == 10);
+ M::const_iterator it = std::next(m.cbegin());
+
+ Moveable mvkey1(2, 2.0);
+ Moveable mv1(4, 4.0);
+ r = m.insert_or_assign(it, std::move(mvkey1), std::move(mv1));
+ assert(m.size() == 10);
+ assert(mv1.moved()); // was moved from
+ assert(!mvkey1.moved()); // was not moved from
+ assert(r->first == mvkey1); // key
+ assert(r->second.get() == 4); // value
+
+ Moveable mvkey2(3, 3.0);
+ Moveable mv2(5, 5.0);
+ r = m.insert_or_assign(it, std::move(mvkey2), std::move(mv2));
+ assert(m.size() == 11);
+ assert(mv2.moved()); // was moved from
+ assert(mvkey2.moved()); // was moved from
+ assert(r->first.get() == 3); // key
+ assert(r->second.get() == 5); // value
+ }
+
+#endif // _LIBCPP_HAS_NO_VARIADICS
+#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
+}
Index: test/std/containers/associative/map/map.modifiers/try.emplace.pass.cpp
===================================================================
--- test/std/containers/associative/map/map.modifiers/try.emplace.pass.cpp
+++ test/std/containers/associative/map/map.modifiers/try.emplace.pass.cpp
@@ -0,0 +1,166 @@
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// UNSUPPORTED: c++03, c++11, c++14
+
+// <map>
+
+// class map
+
+// template <class... Args>
+// pair<iterator, bool> try_emplace(const key_type& k, Args&&... args); // C++17
+// template <class... Args>
+// pair<iterator, bool> try_emplace(key_type&& k, Args&&... args); // C++17
+// template <class... Args>
+// iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args); // C++17
+// template <class... Args>
+// iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args); // C++17
+
+#include <__config>
+#include <map>
+#include <cassert>
+#include <tuple>
+
+class Moveable
+{
+ Moveable(const Moveable&);
+ Moveable& operator=(const Moveable&);
+
+ int int_;
+ double double_;
+public:
+ Moveable() : int_(0), double_(0) {}
+ Moveable(int i, double d) : int_(i), double_(d) {}
+ Moveable(Moveable&& x)
+ : int_(x.int_), double_(x.double_)
+ {x.int_ = -1; x.double_ = -1;}
+ Moveable& operator=(Moveable&& x)
+ {int_ = x.int_; x.int_ = -1;
+ double_ = x.double_; x.double_ = -1;
+ return *this;
+ }
+
+ bool operator==(const Moveable& x) const
+ {return int_ == x.int_ && double_ == x.double_;}
+ bool operator<(const Moveable& x) const
+ {return int_ < x.int_ || (int_ == x.int_ && double_ < x.double_);}
+
+ int get() const {return int_;}
+ bool moved() const {return int_ == -1;}
+};
+
+
+int main()
+{
+#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
+#ifndef _LIBCPP_HAS_NO_VARIADICS
+
+ { // pair<iterator, bool> try_emplace(const key_type& k, Args&&... args);
+ typedef std::map<int, Moveable> M;
+ typedef std::pair<M::iterator, bool> R;
+ M m;
+ R r;
+ for ( int i = 0; i < 20; i += 2 )
+ m.emplace ( i, Moveable(i, (double) i));
+ assert(m.size() == 10);
+
+ Moveable mv1(3, 3.0);
+ r = m.try_emplace(2, std::move(mv1));
+ assert(m.size() == 10);
+ assert(!r.second); // was not inserted
+ assert(!mv1.moved()); // was not moved from
+ assert(r.first->first == 2); // key
+
+ r = m.try_emplace(3, std::move(mv1));
+ assert(m.size() == 11);
+ assert(r.second); // was inserted
+ assert(mv1.moved()); // was moved from
+ assert(r.first->first == 3); // key
+ assert(r.first->second.get() == 3); // value
+ }
+
+ { // pair<iterator, bool> try_emplace(key_type&& k, Args&&... args);
+ typedef std::map<Moveable, Moveable> M;
+ typedef std::pair<M::iterator, bool> R;
+ M m;
+ R r;
+ for ( int i = 0; i < 20; i += 2 )
+ m.emplace ( Moveable(i, (double) i), Moveable(i+1, (double) i+1));
+ assert(m.size() == 10);
+
+ Moveable mvkey1(2, 2.0);
+ Moveable mv1(4, 4.0);
+ r = m.try_emplace(std::move(mvkey1), std::move(mv1));
+ assert(m.size() == 10);
+ assert(!r.second); // was not inserted
+ assert(!mv1.moved()); // was not moved from
+ assert(!mvkey1.moved()); // was not moved from
+ assert(r.first->first == mvkey1); // key
+
+ Moveable mvkey2(3, 3.0);
+ r = m.try_emplace(std::move(mvkey2), std::move(mv1));
+ assert(m.size() == 11);
+ assert(r.second); // was inserted
+ assert(mv1.moved()); // was moved from
+ assert(mvkey2.moved()); // was moved from
+ assert(r.first->first.get() == 3); // key
+ assert(r.first->second.get() == 4); // value
+ }
+
+ { // iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args);
+ typedef std::map<int, Moveable> M;
+ M m;
+ M::iterator r;
+ for ( int i = 0; i < 20; i += 2 )
+ m.emplace ( i, Moveable(i, (double) i));
+ assert(m.size() == 10);
+ Moveable mv1(3, 3.0);
+ M::const_iterator it = m.find(2);
+
+ r = m.try_emplace(it, 2, std::move(mv1));
+ assert(m.size() == 10);
+ assert(!mv1.moved()); // was not moved from
+ assert(r->first == 2); // key
+
+ r = m.try_emplace(it, 3, std::move(mv1));
+ assert(m.size() == 11);
+ assert(mv1.moved()); // was moved from
+ assert(r->first == 3); // key
+ assert(r->second.get() == 3); // value
+ }
+
+ { // iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args);
+ typedef std::map<Moveable, Moveable> M;
+ M m;
+ M::iterator r;
+ for ( int i = 0; i < 20; i += 2 )
+ m.emplace ( Moveable(i, (double) i), Moveable(i+1, (double) i+1));
+ assert(m.size() == 10);
+ M::const_iterator it = std::next(m.cbegin());
+
+ Moveable mvkey1(2, 2.0);
+ Moveable mv1(4, 4.0);
+ r = m.try_emplace(it, std::move(mvkey1), std::move(mv1));
+ assert(m.size() == 10);
+ assert(!mv1.moved()); // was not moved from
+ assert(!mvkey1.moved()); // was not moved from
+ assert(r->first == mvkey1); // key
+
+ Moveable mvkey2(3, 3.0);
+ r = m.try_emplace(it, std::move(mvkey2), std::move(mv1));
+ assert(m.size() == 11);
+ assert(mv1.moved()); // was moved from
+ assert(mvkey2.moved()); // was moved from
+ assert(r->first.get() == 3); // key
+ assert(r->second.get() == 4); // value
+ }
+
+#endif // _LIBCPP_HAS_NO_VARIADICS
+#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
+}
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits