Implement N4279 and LWG#2664 for <map>. Reviewed as http://reviews.llvm.org/D10669
git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@241539 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
		
							
								
								
									
										131
									
								
								include/map
									
									
									
									
									
								
							
							
						
						
									
										131
									
								
								include/map
									
									
									
									
									
								
							@@ -135,6 +135,23 @@ public:
 | 
			
		||||
        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 @@ public:
 | 
			
		||||
 | 
			
		||||
#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
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,192 @@
 | 
			
		||||
//===----------------------------------------------------------------------===//
 | 
			
		||||
//
 | 
			
		||||
//                     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);
 | 
			
		||||
 | 
			
		||||
        for (int i=0; i < 20; i += 2)
 | 
			
		||||
        {
 | 
			
		||||
            Moveable mv(i+1, i+1);
 | 
			
		||||
            r = m.insert_or_assign(i, std::move(mv));
 | 
			
		||||
            assert(m.size() == 10);
 | 
			
		||||
            assert(!r.second);                    // was not inserted
 | 
			
		||||
            assert(mv.moved());                   // was moved from
 | 
			
		||||
            assert(r.first->first == i);          // key
 | 
			
		||||
            assert(r.first->second.get() == i+1); // value
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        Moveable mv1(5, 5.0);
 | 
			
		||||
        r = m.insert_or_assign(-1, std::move(mv1));
 | 
			
		||||
        assert(m.size() == 11);
 | 
			
		||||
        assert(r.second);                    // was inserted
 | 
			
		||||
        assert(mv1.moved());                 // was moved from
 | 
			
		||||
        assert(r.first->first        == -1); // key
 | 
			
		||||
        assert(r.first->second.get() == 5);  // value
 | 
			
		||||
 | 
			
		||||
        Moveable mv2(9, 9.0);
 | 
			
		||||
        r = m.insert_or_assign(3, std::move(mv2));
 | 
			
		||||
        assert(m.size() == 12);
 | 
			
		||||
        assert(r.second);                   // was inserted
 | 
			
		||||
        assert(mv2.moved());                // was moved from
 | 
			
		||||
        assert(r.first->first        == 3); // key
 | 
			
		||||
        assert(r.first->second.get() == 9); // value
 | 
			
		||||
 | 
			
		||||
        Moveable mv3(-1, 5.0);
 | 
			
		||||
        r = m.insert_or_assign(117, std::move(mv3));
 | 
			
		||||
        assert(m.size() == 13);
 | 
			
		||||
        assert(r.second);                     // was inserted
 | 
			
		||||
        assert(mv3.moved());                  // was moved from
 | 
			
		||||
        assert(r.first->first        == 117); // key
 | 
			
		||||
        assert(r.first->second.get() == -1);  // 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
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,189 @@
 | 
			
		||||
//===----------------------------------------------------------------------===//
 | 
			
		||||
//
 | 
			
		||||
//                     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);
 | 
			
		||||
        for (int i=0; i < 20; i += 2)
 | 
			
		||||
        {
 | 
			
		||||
            r = m.try_emplace(i, std::move(mv1));
 | 
			
		||||
            assert(m.size() == 10);
 | 
			
		||||
            assert(!r.second);              // was not inserted
 | 
			
		||||
            assert(!mv1.moved());           // was not moved from
 | 
			
		||||
            assert(r.first->first == i);    // key
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        r = m.try_emplace(-1, std::move(mv1));
 | 
			
		||||
        assert(m.size() == 11);
 | 
			
		||||
        assert(r.second);                   // was inserted
 | 
			
		||||
        assert(mv1.moved());                // was moved from
 | 
			
		||||
        assert(r.first->first == -1);       // key
 | 
			
		||||
        assert(r.first->second.get() == 3); // value
 | 
			
		||||
 | 
			
		||||
        Moveable mv2(5, 3.0);
 | 
			
		||||
        r = m.try_emplace(5, std::move(mv2));
 | 
			
		||||
        assert(m.size() == 12);
 | 
			
		||||
        assert(r.second);                   // was inserted
 | 
			
		||||
        assert(mv2.moved());                // was moved from
 | 
			
		||||
        assert(r.first->first == 5);        // key
 | 
			
		||||
        assert(r.first->second.get() == 5); // value
 | 
			
		||||
 | 
			
		||||
        Moveable mv3(-1, 3.0);
 | 
			
		||||
        r = m.try_emplace(117, std::move(mv2));
 | 
			
		||||
        assert(m.size() == 13);
 | 
			
		||||
        assert(r.second);                    // was inserted
 | 
			
		||||
        assert(mv2.moved());                 // was moved from
 | 
			
		||||
        assert(r.first->first == 117);       // key
 | 
			
		||||
        assert(r.first->second.get() == -1); // 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.try_emplace ( i, Moveable(i, (double) i));
 | 
			
		||||
        assert(m.size() == 10);
 | 
			
		||||
        M::const_iterator it = m.find(2);
 | 
			
		||||
        
 | 
			
		||||
        Moveable mv1(3, 3.0);
 | 
			
		||||
        for (int i=0; i < 20; i += 2)
 | 
			
		||||
        {
 | 
			
		||||
            r = m.try_emplace(it, i, std::move(mv1));
 | 
			
		||||
            assert(m.size() == 10);
 | 
			
		||||
            assert(!mv1.moved());         // was not moved from
 | 
			
		||||
            assert(r->first == i);        // key
 | 
			
		||||
            assert(r->second.get() == i); // value
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        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
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user