[libcxx] r264986 - Teach __tree how to handle map's __value_type

Eric Fiselier via cfe-commits cfe-commits at lists.llvm.org
Wed Mar 30 19:15:17 PDT 2016


Author: ericwf
Date: Wed Mar 30 21:15:15 2016
New Revision: 264986

URL: http://llvm.org/viewvc/llvm-project?rev=264986&view=rev
Log:
Teach __tree how to handle map's __value_type

This patch is fairly large and contains a number of changes. The changes all work towards
allowing __tree to properly handle __value_type esspecially when inserting into the __tree.
I chose not to break this change into smaller patches because it wouldn't be possible to
write meaningful standard-compliant tests for each patch.

It is very similar to r260513 "[libcxx] Teach __hash_table how to handle unordered_map's __hash_value_type".

Changes in <map>
 * Remove __value_type's constructors because it should never be constructed directly.

 * Make map::emplace and multimap::emplace forward to __tree and remove the old definitions

 * Remove "__construct_node" map and multimap member functions. Almost all of the construction is done within __tree.

 * Fix map's move constructor to access "__value_type.__nc" directly and pass this object to __tree::insert.

Changes in <__tree>
 * Add traits to detect, handle, and unwrap, map's "__value_type".

 * Convert methods taking "value_type" to take "__container_value_type" instead. Previously these methods caused
  unwanted implicit conversions from "std::pair<Key, Value>" to "__value_type<Key, Value>".

 * Delete __tree_node and __tree_node_base's constructors and assignment operators. The node types should never be constructed
   because the "__value_" member of __tree_node must be constructed directly by the allocator.

 * Make the __tree_node_destructor class and "__construct_node" methods unwrap "__node_value_type" into "__container_value_type" before invoking the allocator. The user's allocator can only be used to construct and destroy the container's value_type. Passing it map's "__value_type" was incorrect.

 * Cleanup the "__insert" and "__emplace" methods. Have __insert forward to an __emplace function wherever possible to reduce
   code duplication. __insert_unique(value_type const&) and __insert_unique(value_type&&) forward to __emplace_unique_key_args.
   These functions will not allocate a new node if the value is already in the tree.

 * Change the __find* functions to take the "key_type" directly instead of passing in "value_type" and unwrapping the key later.
   This change allows the find functions to be used without having to construct a "value_type" first. This allows for a number
   of optimizations.

 * Teach __move_assign and __assign_multi methods to unwrap map's __value_type.

Added:
    libcxx/trunk/test/std/containers/associative/map/map.modifiers/insert_allocator_requirements.pass.cpp
    libcxx/trunk/test/std/containers/associative/multimap/multimap.modifiers/insert_allocator_requirements.pass.cpp
    libcxx/trunk/test/std/containers/associative/multiset/insert_allocator_requirements.pass.cpp
    libcxx/trunk/test/std/containers/associative/set/insert_allocator_requirements.pass.cpp
Modified:
    libcxx/trunk/include/__config
    libcxx/trunk/include/__tree
    libcxx/trunk/include/map

Modified: libcxx/trunk/include/__config
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/__config?rev=264986&r1=264985&r2=264986&view=diff
==============================================================================
--- libcxx/trunk/include/__config (original)
+++ libcxx/trunk/include/__config Wed Mar 30 21:15:15 2016
@@ -669,6 +669,12 @@ template <unsigned> struct __static_asse
 #define _LIBCPP_DEFAULT = default;
 #endif
 
+#ifdef _LIBCPP_HAS_NO_DELETED_FUNCTIONS
+#define _LIBCPP_EQUAL_DELETE
+#else
+#define _LIBCPP_EQUAL_DELETE = delete
+#endif
+
 #ifdef __GNUC__
 #define _NOALIAS __attribute__((__malloc__))
 #else

Modified: libcxx/trunk/include/__tree
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/__tree?rev=264986&r1=264985&r2=264986&view=diff
==============================================================================
--- libcxx/trunk/include/__tree (original)
+++ libcxx/trunk/include/__tree Wed Mar 30 21:15:15 2016
@@ -510,42 +510,22 @@ __tree_remove(_NodePtr __root, _NodePtr
     }
 }
 
-template <class _Allocator>
-class __tree_node_destructor
-{
-    typedef _Allocator                                      allocator_type;
-    typedef allocator_traits<allocator_type>                __alloc_traits;
-
-public:
-    typedef typename __alloc_traits::pointer                pointer;
-private:
-
-    allocator_type& __na_;
-
-    __tree_node_destructor& operator=(const __tree_node_destructor&);
+// node traits
 
-public:
-    bool __value_constructed;
 
-    _LIBCPP_INLINE_VISIBILITY
-    explicit __tree_node_destructor(allocator_type& __na, bool __val = false) _NOEXCEPT
-        : __na_(__na),
-          __value_constructed(__val)
-        {}
+#ifndef _LIBCPP_CXX03_LANG
+template <class _Tp>
+struct __is_tree_value_type_imp : false_type {};
 
-    _LIBCPP_INLINE_VISIBILITY
-    void operator()(pointer __p) _NOEXCEPT
-    {
-        if (__value_constructed)
-            __alloc_traits::destroy(__na_, _VSTD::addressof(__p->__value_));
-        if (__p)
-            __alloc_traits::deallocate(__na_, __p, 1);
-    }
+template <class _Key, class _Value>
+struct __is_tree_value_type_imp<__value_type<_Key, _Value>> : true_type {};
 
-    template <class> friend class __map_node_destructor;
-};
+template <class ..._Args>
+struct __is_tree_value_type : false_type {};
 
-// node traits
+template <class _One>
+struct __is_tree_value_type<_One> : __is_tree_value_type_imp<typename __uncvref<_One>::type> {};
+#endif
 
 template <class _Tp>
 struct __tree_key_value_types {
@@ -553,6 +533,26 @@ struct __tree_key_value_types {
   typedef _Tp __node_value_type;
   typedef _Tp __container_value_type;
   static const bool __is_map = false;
+
+  _LIBCPP_INLINE_VISIBILITY
+  static key_type const& __get_key(_Tp const& __v) {
+    return __v;
+  }
+  _LIBCPP_INLINE_VISIBILITY
+  static __container_value_type const& __get_value(__node_value_type const& __v) {
+    return __v;
+  }
+  _LIBCPP_INLINE_VISIBILITY
+  static __container_value_type* __get_ptr(__node_value_type& __n) {
+    return _VSTD::addressof(__n);
+  }
+
+#ifndef _LIBCPP_CXX03_LANG
+  _LIBCPP_INLINE_VISIBILITY
+  static  __container_value_type&& __move(__node_value_type& __v) {
+    return _VSTD::move(__v);
+  }
+#endif
 };
 
 template <class _Key, class _Tp>
@@ -564,6 +564,46 @@ struct __tree_key_value_types<__value_ty
   typedef pair<_Key, _Tp>                              __nc_value_type;
   typedef __container_value_type                       __map_value_type;
   static const bool __is_map = true;
+
+  _LIBCPP_INLINE_VISIBILITY
+  static key_type const&
+  __get_key(__node_value_type const& __t) {
+    return __t.__cc.first;
+  }
+
+  template <class _Up>
+  _LIBCPP_INLINE_VISIBILITY
+  static typename enable_if<__is_same_uncvref<_Up, __container_value_type>::value,
+      key_type const&>::type
+  __get_key(_Up& __t) {
+    return __t.first;
+  }
+
+  _LIBCPP_INLINE_VISIBILITY
+  static __container_value_type const&
+  __get_value(__node_value_type const& __t) {
+    return __t.__cc;
+  }
+
+  template <class _Up>
+  _LIBCPP_INLINE_VISIBILITY
+  static typename enable_if<__is_same_uncvref<_Up, __container_value_type>::value,
+      __container_value_type const&>::type
+  __get_value(_Up& __t) {
+    return __t;
+  }
+
+  _LIBCPP_INLINE_VISIBILITY
+  static __container_value_type* __get_ptr(__node_value_type& __n) {
+    return _VSTD::addressof(__n.__cc);
+  }
+
+#ifndef _LIBCPP_CXX03_LANG
+  _LIBCPP_INLINE_VISIBILITY
+  static  __nc_value_type&& __move(__node_value_type& __v) {
+    return _VSTD::move(__v.__nc);
+  }
+#endif
 };
 
 template <class _VoidPtr>
@@ -650,8 +690,6 @@ class __tree_node_base
 {
     typedef __tree_node_base_types<_VoidPtr> _NodeBaseTypes;
 
-    __tree_node_base(const __tree_node_base&);
-    __tree_node_base& operator=(const __tree_node_base&);
 public:
     typedef typename _NodeBaseTypes::__node_base_pointer pointer;
 
@@ -659,9 +697,10 @@ public:
     pointer __parent_;
     bool __is_black_;
 
-    _LIBCPP_INLINE_VISIBILITY
-    __tree_node_base() _NOEXCEPT
-        : __right_(), __parent_(), __is_black_(false) {}
+private:
+  ~__tree_node_base() _LIBCPP_EQUAL_DELETE;
+  __tree_node_base(__tree_node_base const&) _LIBCPP_EQUAL_DELETE;
+  __tree_node_base& operator=(__tree_node_base const&) _LIBCPP_EQUAL_DELETE;
 };
 
 template <class _Tp, class _VoidPtr>
@@ -673,18 +712,49 @@ public:
 
     __node_value_type __value_;
 
-#if !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS)
-    template <class ..._Args>
-        _LIBCPP_INLINE_VISIBILITY
-        explicit __tree_node(_Args&& ...__args)
-            : __value_(_VSTD::forward<_Args>(__args)...) {}
-#else  // !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS)
-    _LIBCPP_INLINE_VISIBILITY
-    explicit __tree_node(const __node_value_type& __v)
-            : __value_(__v) {}
-#endif  // !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS)
+private:
+  ~__tree_node() _LIBCPP_EQUAL_DELETE;
+  __tree_node(__tree_node const&) _LIBCPP_EQUAL_DELETE;
+  __tree_node& operator=(__tree_node const&) _LIBCPP_EQUAL_DELETE;
 };
 
+
+template <class _Allocator>
+class __tree_node_destructor
+{
+    typedef _Allocator                                      allocator_type;
+    typedef allocator_traits<allocator_type>                __alloc_traits;
+
+public:
+    typedef typename __alloc_traits::pointer                pointer;
+private:
+    typedef __tree_node_types<pointer> _NodeTypes;
+    allocator_type& __na_;
+
+    __tree_node_destructor& operator=(const __tree_node_destructor&);
+
+public:
+    bool __value_constructed;
+
+    _LIBCPP_INLINE_VISIBILITY
+    explicit __tree_node_destructor(allocator_type& __na, bool __val = false) _NOEXCEPT
+        : __na_(__na),
+          __value_constructed(__val)
+        {}
+
+    _LIBCPP_INLINE_VISIBILITY
+    void operator()(pointer __p) _NOEXCEPT
+    {
+        if (__value_constructed)
+            __alloc_traits::destroy(__na_, _NodeTypes::__get_ptr(__p->__value_));
+        if (__p)
+            __alloc_traits::deallocate(__na_, __p, 1);
+    }
+
+    template <class> friend class __map_node_destructor;
+};
+
+
 template <class _Tp, class _NodePtr, class _DiffType>
 class _LIBCPP_TYPE_VIS_ONLY __tree_iterator
 {
@@ -840,6 +910,7 @@ private:
     typedef typename __make_tree_node_types<value_type,
         typename __alloc_traits::void_pointer>::type
                                                     _NodeTypes;
+    typedef typename _NodeTypes::key_type           key_type;
 public:
     typedef typename _NodeTypes::__node_value_type      __node_value_type;
     typedef typename _NodeTypes::__container_value_type __container_value_type;
@@ -983,44 +1054,104 @@ public:
 #endif
             );
 
-#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
-#ifndef _LIBCPP_HAS_NO_VARIADICS
+
+#ifndef _LIBCPP_CXX03_LANG
+    template <class _Key, class ..._Args>
+    pair<iterator, bool>
+    __emplace_unique_key_args(_Key const&, _Args&&... __args);
+    template <class _Key, class ..._Args>
+    iterator
+    __emplace_hint_unique_key_args(const_iterator, _Key const&, _Args&&...);
+
     template <class... _Args>
-        pair<iterator, bool>
-        __emplace_unique(_Args&&... __args);
+    pair<iterator, bool> __emplace_unique(_Args&&... __args);
+
     template <class... _Args>
-        iterator
-        __emplace_multi(_Args&&... __args);
+    iterator __emplace_hint_unique(const_iterator __p, _Args&&... __args);
 
     template <class... _Args>
-        iterator
-        __emplace_hint_unique(const_iterator __p, _Args&&... __args);
+    iterator __emplace_multi(_Args&&... __args);
+
     template <class... _Args>
-        iterator
-        __emplace_hint_multi(const_iterator __p, _Args&&... __args);
-#endif  // _LIBCPP_HAS_NO_VARIADICS
+    iterator __emplace_hint_multi(const_iterator __p, _Args&&... __args);
+#else
+    template <class _Key, class _Args>
+    _LIBCPP_INLINE_VISIBILITY
+    pair<iterator, bool> __emplace_unique_key_args(_Key const&, _Args& __args);
+    template <class _Key, class _Args>
+    _LIBCPP_INLINE_VISIBILITY
+    iterator __emplace_hint_unique_key_args(const_iterator, _Key const&, _Args&);
+#endif
+
+    _LIBCPP_INLINE_VISIBILITY
+    pair<iterator, bool> __insert_unique(const __container_value_type& __v) {
+        return __emplace_unique_key_args(_NodeTypes::__get_key(__v), __v);
+    }
+
+    _LIBCPP_INLINE_VISIBILITY
+    iterator __insert_unique(const_iterator __p, const __container_value_type& __v) {
+        return __emplace_hint_unique_key_args(__p, _NodeTypes::__get_key(__v), __v);
+    }
+
+#ifdef _LIBCPP_CXX03_LANG
+    _LIBCPP_INLINE_VISIBILITY
+    iterator __insert_multi(const __container_value_type& __v);
+    _LIBCPP_INLINE_VISIBILITY
+    iterator __insert_multi(const_iterator __p, const __container_value_type& __v);
+#else
+    _LIBCPP_INLINE_VISIBILITY
+    pair<iterator, bool> __insert_unique(__container_value_type&& __v) {
+        return __emplace_unique_key_args(_NodeTypes::__get_key(__v), _VSTD::move(__v));
+    }
+
+    _LIBCPP_INLINE_VISIBILITY
+    iterator __insert_unique(const_iterator __p, __container_value_type&& __v) {
+        return __emplace_hint_unique_key_args(__p, _NodeTypes::__get_key(__v), _VSTD::move(__v));
+    }
+
+    template <class _Vp, class = typename enable_if<
+            !is_same<typename __unconstref<_Vp>::type,
+                     __container_value_type
+            >::value
+        >::type>
+    _LIBCPP_INLINE_VISIBILITY
+    pair<iterator, bool> __insert_unique(_Vp&& __v) {
+        return __emplace_unique(_VSTD::forward<_Vp>(__v));
+    }
+
+    template <class _Vp, class = typename enable_if<
+            !is_same<typename __unconstref<_Vp>::type,
+                     __container_value_type
+            >::value
+        >::type>
+    _LIBCPP_INLINE_VISIBILITY
+    iterator __insert_unique(const_iterator __p, _Vp&& __v) {
+        return __emplace_hint_unique(__p, _VSTD::forward<_Vp>(__v));
+    }
+
+    _LIBCPP_INLINE_VISIBILITY
+    iterator __insert_multi(__container_value_type&& __v) {
+        return __emplace_multi(_VSTD::move(__v));
+    }
+
+    _LIBCPP_INLINE_VISIBILITY
+    iterator __insert_multi(const_iterator __p, __container_value_type&& __v) {
+        return __emplace_hint_multi(__p, _VSTD::move(__v));
+    }
 
     template <class _Vp>
-        pair<iterator, bool> __insert_unique(_Vp&& __v);
-    template <class _Vp>
-        iterator __insert_unique(const_iterator __p, _Vp&& __v);
-    template <class _Vp>
-        iterator __insert_multi(_Vp&& __v);
-    template <class _Vp>
-        iterator __insert_multi(const_iterator __p, _Vp&& __v);
-#endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
+    _LIBCPP_INLINE_VISIBILITY
+    iterator __insert_multi(_Vp&& __v) {
+        return __emplace_multi(_VSTD::forward<_Vp>(__v));
+    }
 
-    pair<iterator, bool> __insert_unique(const value_type& __v);
-    iterator __insert_unique(const_iterator __p, const value_type& __v);
-    iterator __insert_multi(const value_type& __v);
-    iterator __insert_multi(const_iterator __p, const value_type& __v);
+    template <class _Vp>
+    _LIBCPP_INLINE_VISIBILITY
+    iterator __insert_multi(const_iterator __p, _Vp&& __v) {
+        return __emplace_hint_multi(__p, _VSTD::forward<_Vp>(__v));
+    }
 
-#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
-    pair<iterator, bool> __insert_unique(        value_type&& __v);
-    iterator __insert_unique(const_iterator __p, value_type&& __v);
-    iterator __insert_multi(                    value_type&& __v);
-    iterator __insert_multi(const_iterator __p, value_type&& __v);
-#endif
+#endif // !_LIBCPP_CXX03_LANG
 
     pair<iterator, bool> __node_insert_unique(__node_pointer __nd);
     iterator             __node_insert_unique(const_iterator __p,
@@ -1102,12 +1233,12 @@ public:
     __node_holder remove(const_iterator __p) _NOEXCEPT;
 private:
     typename __node_base::pointer&
-        __find_leaf_low(typename __node_base::pointer& __parent, const value_type& __v);
+        __find_leaf_low(typename __node_base::pointer& __parent, const key_type& __v);
     typename __node_base::pointer&
-        __find_leaf_high(typename __node_base::pointer& __parent, const value_type& __v);
+        __find_leaf_high(typename __node_base::pointer& __parent, const key_type& __v);
     typename __node_base::pointer&
         __find_leaf(const_iterator __hint,
-                    typename __node_base::pointer& __parent, const value_type& __v);
+                    typename __node_base::pointer& __parent, const key_type& __v);
     template <class _Key>
         typename __node_base::pointer&
         __find_equal(typename __node_base::pointer& __parent, const _Key& __v);
@@ -1116,11 +1247,11 @@ private:
         __find_equal(const_iterator __hint, typename __node_base::pointer& __parent,
                      const _Key& __v);
 
-#if !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS)
+#ifndef _LIBCPP_CXX03_LANG
     template <class ..._Args>
-        __node_holder __construct_node(_Args&& ...__args);
-#else  // !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS)
-        __node_holder __construct_node(const value_type& __v);
+    __node_holder __construct_node(_Args&& ...__args);
+#else
+    __node_holder __construct_node(const __container_value_type& __v);
 #endif
 
     void destroy(__node_pointer __nd) _NOEXCEPT;
@@ -1254,6 +1385,11 @@ template <class _InputIterator>
 void
 __tree<_Tp, _Compare, _Allocator>::__assign_unique(_InputIterator __first, _InputIterator __last)
 {
+    typedef iterator_traits<_InputIterator> _ITraits;
+    typedef typename _ITraits::value_type _ItValueType;
+    static_assert((is_same<_ItValueType, __container_value_type>::value),
+                  "__assign_unique may only be called with the containers value type");
+
     if (size() != 0)
     {
         __node_pointer __cache = __detach();
@@ -1294,6 +1430,12 @@ template <class _InputIterator>
 void
 __tree<_Tp, _Compare, _Allocator>::__assign_multi(_InputIterator __first, _InputIterator __last)
 {
+    typedef iterator_traits<_InputIterator> _ITraits;
+    typedef typename _ITraits::value_type _ItValueType;
+    static_assert((is_same<_ItValueType, __container_value_type>::value ||
+                  is_same<_ItValueType, __node_value_type>::value),
+                  "__assign_multi may only be called with the containers value type"
+                  " or the nodes value type");
     if (size() != 0)
     {
         __node_pointer __cache = __detach();
@@ -1326,7 +1468,7 @@ __tree<_Tp, _Compare, _Allocator>::__ass
         }
     }
     for (; __first != __last; ++__first)
-        __insert_multi(*__first);
+        __insert_multi(_NodeTypes::__get_value(*__first));
 }
 
 template <class _Tp, class _Compare, class _Allocator>
@@ -1450,7 +1592,7 @@ __tree<_Tp, _Compare, _Allocator>::__mov
             }
         }
         while (__t.size() != 0)
-            __insert_multi(__e, _VSTD::move(__t.remove(__t.begin())->__value_));
+            __insert_multi(__e, _NodeTypes::__move(__t.remove(__t.begin())->__value_));
     }
 }
 
@@ -1485,7 +1627,7 @@ __tree<_Tp, _Compare, _Allocator>::destr
         destroy(static_cast<__node_pointer>(__nd->__left_));
         destroy(static_cast<__node_pointer>(__nd->__right_));
         __node_allocator& __na = __node_alloc();
-        __node_traits::destroy(__na, _VSTD::addressof(__nd->__value_));
+        __node_traits::destroy(__na, _NodeTypes::__get_ptr(__nd->__value_));
         __node_traits::deallocate(__na, __nd, 1);
     }
 }
@@ -1532,7 +1674,7 @@ __tree<_Tp, _Compare, _Allocator>::clear
 template <class _Tp, class _Compare, class _Allocator>
 typename __tree<_Tp, _Compare, _Allocator>::__node_base::pointer&
 __tree<_Tp, _Compare, _Allocator>::__find_leaf_low(typename __node_base::pointer& __parent,
-                                                   const value_type& __v)
+                                                   const key_type& __v)
 {
     __node_pointer __nd = __root();
     if (__nd != nullptr)
@@ -1571,7 +1713,7 @@ __tree<_Tp, _Compare, _Allocator>::__fin
 template <class _Tp, class _Compare, class _Allocator>
 typename __tree<_Tp, _Compare, _Allocator>::__node_base::pointer&
 __tree<_Tp, _Compare, _Allocator>::__find_leaf_high(typename __node_base::pointer& __parent,
-                                                    const value_type& __v)
+                                                    const key_type& __v)
 {
     __node_pointer __nd = __root();
     if (__nd != nullptr)
@@ -1614,7 +1756,7 @@ template <class _Tp, class _Compare, cla
 typename __tree<_Tp, _Compare, _Allocator>::__node_base::pointer&
 __tree<_Tp, _Compare, _Allocator>::__find_leaf(const_iterator __hint,
                                                typename __node_base::pointer& __parent,
-                                               const value_type& __v)
+                                               const key_type& __v)
 {
     if (__hint == end() || !value_comp()(*__hint, __v))  // check before
     {
@@ -1757,6 +1899,7 @@ __tree<_Tp, _Compare, _Allocator>::__ins
     __new_node->__left_   = nullptr;
     __new_node->__right_  = nullptr;
     __new_node->__parent_ = __parent;
+    // __new_node->__is_black_ is initialized in __tree_balance_after_insert
     __child = __new_node;
     if (__begin_node()->__left_ != nullptr)
         __begin_node() = static_cast<__node_pointer>(__begin_node()->__left_);
@@ -1764,21 +1907,85 @@ __tree<_Tp, _Compare, _Allocator>::__ins
     ++size();
 }
 
-#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
-#ifndef _LIBCPP_HAS_NO_VARIADICS
+#ifndef _LIBCPP_CXX03_LANG
+template <class _Tp, class _Compare, class _Allocator>
+template <class _Key, class... _Args>
+pair<typename __tree<_Tp, _Compare, _Allocator>::iterator, bool>
+__tree<_Tp, _Compare, _Allocator>::__emplace_unique_key_args(_Key const& __k, _Args&&... __args)
+#else
+template <class _Tp, class _Compare, class _Allocator>
+template <class _Key, class _Args>
+pair<typename __tree<_Tp, _Compare, _Allocator>::iterator, bool>
+__tree<_Tp, _Compare, _Allocator>::__emplace_unique_key_args(_Key const& __k, _Args& __args)
+#endif
+{
+    __node_base_pointer __parent;
+    __node_base_pointer& __child = __find_equal(__parent, __k);
+    __node_pointer __r = static_cast<__node_pointer>(__child);
+    bool __inserted = false;
+    if (__child == nullptr)
+    {
+#ifndef _LIBCPP_CXX03_LANG
+        __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...);
+#else
+        __node_holder __h = __construct_node(__args);
+#endif
+        __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get()));
+        __r = __h.release();
+        __inserted = true;
+    }
+    return pair<iterator, bool>(iterator(__r), __inserted);
+}
+
+
+#ifndef _LIBCPP_CXX03_LANG
+template <class _Tp, class _Compare, class _Allocator>
+template <class _Key, class... _Args>
+typename __tree<_Tp, _Compare, _Allocator>::iterator
+__tree<_Tp, _Compare, _Allocator>::__emplace_hint_unique_key_args(
+    const_iterator __p, _Key const& __k, _Args&&... __args)
+#else
+template <class _Tp, class _Compare, class _Allocator>
+template <class _Key, class _Args>
+typename __tree<_Tp, _Compare, _Allocator>::iterator
+__tree<_Tp, _Compare, _Allocator>::__emplace_hint_unique_key_args(
+    const_iterator __p, _Key const& __k, _Args& __args)
+#endif
+{
+    __node_base_pointer __parent;
+    __node_base_pointer& __child = __find_equal(__p, __parent, __k);
+    __node_pointer __r = static_cast<__node_pointer>(__child);
+    if (__child == nullptr)
+    {
+#ifndef _LIBCPP_CXX03_LANG
+        __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...);
+#else
+        __node_holder __h = __construct_node(__args);
+#endif
+        __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get()));
+        __r = __h.release();
+    }
+    return iterator(__r);
+}
+
+
+#ifndef _LIBCPP_CXX03_LANG
 
 template <class _Tp, class _Compare, class _Allocator>
 template <class ..._Args>
 typename __tree<_Tp, _Compare, _Allocator>::__node_holder
 __tree<_Tp, _Compare, _Allocator>::__construct_node(_Args&& ...__args)
 {
+    static_assert(!__is_tree_value_type<_Args...>::value,
+                  "Cannot construct from __value_type");
     __node_allocator& __na = __node_alloc();
     __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na));
-    __node_traits::construct(__na, _VSTD::addressof(__h->__value_), _VSTD::forward<_Args>(__args)...);
+    __node_traits::construct(__na, _NodeTypes::__get_ptr(__h->__value_), _VSTD::forward<_Args>(__args)...);
     __h.get_deleter().__value_constructed = true;
     return __h;
 }
 
+
 template <class _Tp, class _Compare, class _Allocator>
 template <class... _Args>
 pair<typename __tree<_Tp, _Compare, _Allocator>::iterator, bool>
@@ -1822,7 +2029,7 @@ __tree<_Tp, _Compare, _Allocator>::__emp
 {
     __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...);
     __node_base_pointer __parent;
-    __node_base_pointer& __child = __find_leaf_high(__parent, __h->__value_);
+    __node_base_pointer& __child = __find_leaf_high(__parent, _NodeTypes::__get_key(__h->__value_));
     __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get()));
     return iterator(static_cast<__node_pointer>(__h.release()));
 }
@@ -1835,160 +2042,34 @@ __tree<_Tp, _Compare, _Allocator>::__emp
 {
     __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...);
     __node_base_pointer __parent;
-    __node_base_pointer& __child = __find_leaf(__p, __parent, __h->__value_);
+    __node_base_pointer& __child = __find_leaf(__p, __parent, _NodeTypes::__get_key(__h->__value_));
     __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get()));
     return iterator(static_cast<__node_pointer>(__h.release()));
 }
 
-#endif  // _LIBCPP_HAS_NO_VARIADICS
 
-template <class _Tp, class _Compare, class _Allocator>
-pair<typename __tree<_Tp, _Compare, _Allocator>::iterator, bool>
-__tree<_Tp, _Compare, _Allocator>::__insert_unique(value_type&& __v)
-{
-    __node_holder __h = __construct_node(_VSTD::forward<value_type>(__v));
-    pair<iterator, bool> __r = __node_insert_unique(__h.get());
-    if (__r.second)
-        __h.release();
-    return __r;
-}
-
-template <class _Tp, class _Compare, class _Allocator>
-typename __tree<_Tp, _Compare, _Allocator>::iterator
-__tree<_Tp, _Compare, _Allocator>::__insert_unique(const_iterator __p, value_type&& __v)
-{
-    __node_holder __h = __construct_node(_VSTD::forward<value_type>(__v));
-    iterator __r = __node_insert_unique(__p, __h.get());
-    if (__r.__ptr_ == __h.get())
-        __h.release();
-    return __r;
-}
-
-template <class _Tp, class _Compare, class _Allocator>
-template <class _Vp>
-pair<typename __tree<_Tp, _Compare, _Allocator>::iterator, bool>
-__tree<_Tp, _Compare, _Allocator>::__insert_unique(_Vp&& __v)
-{
-    __node_holder __h = __construct_node(_VSTD::forward<_Vp>(__v));
-    pair<iterator, bool> __r = __node_insert_unique(__h.get());
-    if (__r.second)
-        __h.release();
-    return __r;
-}
-
-template <class _Tp, class _Compare, class _Allocator>
-template <class _Vp>
-typename __tree<_Tp, _Compare, _Allocator>::iterator
-__tree<_Tp, _Compare, _Allocator>::__insert_unique(const_iterator __p, _Vp&& __v)
-{
-    __node_holder __h = __construct_node(_VSTD::forward<_Vp>(__v));
-    iterator __r = __node_insert_unique(__p, __h.get());
-    if (__r.__ptr_ == __h.get())
-        __h.release();
-    return __r;
-}
-
-template <class _Tp, class _Compare, class _Allocator>
-typename __tree<_Tp, _Compare, _Allocator>::iterator
-__tree<_Tp, _Compare, _Allocator>::__insert_multi(value_type&& __v)
-{
-    __node_base_pointer __parent;
-    __node_base_pointer& __child = __find_leaf_high(__parent, __v);
-    __node_holder __h = __construct_node(_VSTD::forward<value_type>(__v));
-    __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get()));
-    return iterator(__h.release());
-}
-
-template <class _Tp, class _Compare, class _Allocator>
-typename __tree<_Tp, _Compare, _Allocator>::iterator
-__tree<_Tp, _Compare, _Allocator>::__insert_multi(const_iterator __p, value_type&& __v)
-{
-    __node_base_pointer __parent;
-    __node_base_pointer& __child = __find_leaf(__p, __parent, __v);
-    __node_holder __h = __construct_node(_VSTD::forward<value_type>(__v));
-    __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get()));
-    return iterator(__h.release());
-}
-
-template <class _Tp, class _Compare, class _Allocator>
-template <class _Vp>
-typename __tree<_Tp, _Compare, _Allocator>::iterator
-__tree<_Tp, _Compare, _Allocator>::__insert_multi(_Vp&& __v)
-{
-    __node_holder __h = __construct_node(_VSTD::forward<_Vp>(__v));
-    __node_base_pointer __parent;
-    __node_base_pointer& __child = __find_leaf_high(__parent, __h->__value_);
-    __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get()));
-    return iterator(__h.release());
-}
-
-template <class _Tp, class _Compare, class _Allocator>
-template <class _Vp>
-typename __tree<_Tp, _Compare, _Allocator>::iterator
-__tree<_Tp, _Compare, _Allocator>::__insert_multi(const_iterator __p, _Vp&& __v)
-{
-    __node_holder __h = __construct_node(_VSTD::forward<_Vp>(__v));
-    __node_base_pointer __parent;
-    __node_base_pointer& __child = __find_leaf(__p, __parent, __h->__value_);
-    __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get()));
-    return iterator(__h.release());
-}
-
-#else  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
+#else  // _LIBCPP_CXX03_LANG
 
 template <class _Tp, class _Compare, class _Allocator>
 typename __tree<_Tp, _Compare, _Allocator>::__node_holder
-__tree<_Tp, _Compare, _Allocator>::__construct_node(const value_type& __v)
+__tree<_Tp, _Compare, _Allocator>::__construct_node(const __container_value_type& __v)
 {
     __node_allocator& __na = __node_alloc();
     __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na));
-    __node_traits::construct(__na, _VSTD::addressof(__h->__value_), __v);
+    __node_traits::construct(__na, _NodeTypes::__get_ptr(__h->__value_), __v);
     __h.get_deleter().__value_constructed = true;
     return _LIBCPP_EXPLICIT_MOVE(__h);  // explicitly moved for C++03
 }
 
-#endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
-
-template <class _Tp, class _Compare, class _Allocator>
-pair<typename __tree<_Tp, _Compare, _Allocator>::iterator, bool>
-__tree<_Tp, _Compare, _Allocator>::__insert_unique(const value_type& __v)
-{
-    __node_base_pointer __parent;
-    __node_base_pointer& __child = __find_equal(__parent, __v);
-    __node_pointer __r = static_cast<__node_pointer>(__child);
-    bool __inserted = false;
-    if (__child == nullptr)
-    {
-        __node_holder __h = __construct_node(__v);
-        __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get()));
-        __r = __h.release();
-        __inserted = true;
-    }
-    return pair<iterator, bool>(iterator(__r), __inserted);
-}
+#endif  // _LIBCPP_CXX03_LANG
 
+#ifdef _LIBCPP_CXX03_LANG
 template <class _Tp, class _Compare, class _Allocator>
 typename __tree<_Tp, _Compare, _Allocator>::iterator
-__tree<_Tp, _Compare, _Allocator>::__insert_unique(const_iterator __p, const value_type& __v)
+__tree<_Tp, _Compare, _Allocator>::__insert_multi(const __container_value_type& __v)
 {
     __node_base_pointer __parent;
-    __node_base_pointer& __child = __find_equal(__p, __parent, __v);
-    __node_pointer __r = static_cast<__node_pointer>(__child);
-    if (__child == nullptr)
-    {
-        __node_holder __h = __construct_node(__v);
-        __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get()));
-        __r = __h.release();
-    }
-    return iterator(__r);
-}
-
-template <class _Tp, class _Compare, class _Allocator>
-typename __tree<_Tp, _Compare, _Allocator>::iterator
-__tree<_Tp, _Compare, _Allocator>::__insert_multi(const value_type& __v)
-{
-    __node_base_pointer __parent;
-    __node_base_pointer& __child = __find_leaf_high(__parent, __v);
+    __node_base_pointer& __child = __find_leaf_high(__parent, _NodeTypes::__get_key(__v));
     __node_holder __h = __construct_node(__v);
     __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get()));
     return iterator(__h.release());
@@ -1996,14 +2077,15 @@ __tree<_Tp, _Compare, _Allocator>::__ins
 
 template <class _Tp, class _Compare, class _Allocator>
 typename __tree<_Tp, _Compare, _Allocator>::iterator
-__tree<_Tp, _Compare, _Allocator>::__insert_multi(const_iterator __p, const value_type& __v)
+__tree<_Tp, _Compare, _Allocator>::__insert_multi(const_iterator __p, const __container_value_type& __v)
 {
     __node_base_pointer __parent;
-    __node_base_pointer& __child = __find_leaf(__p, __parent, __v);
+    __node_base_pointer& __child = __find_leaf(__p, __parent, _NodeTypes::__get_key(__v));
     __node_holder __h = __construct_node(__v);
     __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get()));
     return iterator(__h.release());
 }
+#endif
 
 template <class _Tp, class _Compare, class _Allocator>
 pair<typename __tree<_Tp, _Compare, _Allocator>::iterator, bool>
@@ -2043,7 +2125,7 @@ typename __tree<_Tp, _Compare, _Allocato
 __tree<_Tp, _Compare, _Allocator>::__node_insert_multi(__node_pointer __nd)
 {
     __node_base_pointer __parent;
-    __node_base_pointer& __child = __find_leaf_high(__parent, __nd->__value_);
+    __node_base_pointer& __child = __find_leaf_high(__parent, _NodeTypes::__get_key(__nd->__value_));
     __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__nd));
     return iterator(__nd);
 }
@@ -2054,7 +2136,7 @@ __tree<_Tp, _Compare, _Allocator>::__nod
                                                        __node_pointer __nd)
 {
     __node_base_pointer __parent;
-    __node_base_pointer& __child = __find_leaf(__p, __parent, __nd->__value_);
+    __node_base_pointer& __child = __find_leaf(__p, __parent, _NodeTypes::__get_key(__nd->__value_));
     __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__nd));
     return iterator(__nd);
 }
@@ -2072,7 +2154,8 @@ __tree<_Tp, _Compare, _Allocator>::erase
     __node_allocator& __na = __node_alloc();
     __tree_remove(__end_node()->__left_,
                   static_cast<__node_base_pointer>(__np));
-    __node_traits::destroy(__na, const_cast<value_type*>(_VSTD::addressof(*__p)));
+    __node_traits::destroy(__na, _NodeTypes::__get_ptr(
+        const_cast<__node_value_type&>(*__p)));
     __node_traits::deallocate(__na, __np, 1);
     return __r;
 }

Modified: libcxx/trunk/include/map
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/map?rev=264986&r1=264985&r2=264986&view=diff
==============================================================================
--- libcxx/trunk/include/map (original)
+++ libcxx/trunk/include/map Wed Mar 30 21:15:15 2016
@@ -626,33 +626,29 @@ union __value_type
     value_type __cc;
     __nc_value_type __nc;
 
-    template <class ..._Args>
-    _LIBCPP_INLINE_VISIBILITY
-    __value_type(_Args&& ...__args)
-        : __cc(std::forward<_Args>(__args)...) {}
-
-    _LIBCPP_INLINE_VISIBILITY
-    __value_type(const __value_type& __v)
-        : __cc(__v.__cc) {}
-
-    _LIBCPP_INLINE_VISIBILITY
-    __value_type(__value_type& __v)
-        : __cc(__v.__cc) {}
-
-    _LIBCPP_INLINE_VISIBILITY
-    __value_type(__value_type&& __v)
-        : __nc(std::move(__v.__nc)) {}
-
     _LIBCPP_INLINE_VISIBILITY
     __value_type& operator=(const __value_type& __v)
         {__nc = __v.__cc; return *this;}
 
     _LIBCPP_INLINE_VISIBILITY
     __value_type& operator=(__value_type&& __v)
-        {__nc = std::move(__v.__nc); return *this;}
+        {__nc = _VSTD::move(__v.__nc); return *this;}
 
+    template <class _ValueTp,
+              class = typename enable_if<
+                    __is_same_uncvref<_ValueTp, value_type>::value
+                 >::type
+             >
     _LIBCPP_INLINE_VISIBILITY
-    ~__value_type() {__cc.~value_type();}
+    __value_type& operator=(_ValueTp&& __v) {
+        __nc = _VSTD::forward<_ValueTp>(__v); return *this;
+    }
+
+private:
+    __value_type() _LIBCPP_EQUAL_DELETE;
+    ~__value_type() _LIBCPP_EQUAL_DELETE;
+    __value_type(const __value_type& __v) _LIBCPP_EQUAL_DELETE;
+    __value_type(__value_type&& __v) _LIBCPP_EQUAL_DELETE;
 };
 
 #else
@@ -666,18 +662,11 @@ struct __value_type
 
     value_type __cc;
 
-    _LIBCPP_INLINE_VISIBILITY
-    __value_type() {}
-
-    template <class _A0>
-    _LIBCPP_INLINE_VISIBILITY
-    __value_type(const _A0& __a0)
-        : __cc(__a0) {}
-
-    template <class _A0, class _A1>
-    _LIBCPP_INLINE_VISIBILITY
-    __value_type(const _A0& __a0, const _A1& __a1)
-        : __cc(__a0, __a1) {}
+private:
+   __value_type();
+   __value_type(__value_type const&);
+   __value_type& operator=(__value_type const&);
+   ~__value_type();
 };
 
 #endif
@@ -1051,18 +1040,18 @@ public:
     _LIBCPP_INLINE_VISIBILITY
     value_compare  value_comp()    const {return value_compare(__tree_.value_comp().key_comp());}
 
-#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
-#ifndef _LIBCPP_HAS_NO_VARIADICS
-
+#ifndef _LIBCPP_CXX03_LANG
     template <class ..._Args>
-        pair<iterator, bool>
-        emplace(_Args&& ...__args);
+    _LIBCPP_INLINE_VISIBILITY
+    pair<iterator, bool> emplace(_Args&& ...__args) {
+        return __tree_.__emplace_unique(_VSTD::forward<_Args>(__args)...);
+    }
 
     template <class ..._Args>
-        iterator
-        emplace_hint(const_iterator __p, _Args&& ...__args);
-
-#endif  // _LIBCPP_HAS_NO_VARIADICS
+    _LIBCPP_INLINE_VISIBILITY
+    iterator emplace_hint(const_iterator __p, _Args&& ...__args) {
+        return __tree_.__emplace_hint_unique(__p.__i_, _VSTD::forward<_Args>(__args)...);
+    }
 
     template <class _Pp,
               class = typename enable_if<is_constructible<value_type, _Pp>::value>::type>
@@ -1076,7 +1065,7 @@ public:
         iterator insert(const_iterator __pos, _Pp&& __p)
             {return __tree_.__insert_unique(__pos.__i_, _VSTD::forward<_Pp>(__p));}
 
-#endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
+#endif  // _LIBCPP_CXX03_LANG
 
     _LIBCPP_INLINE_VISIBILITY
     pair<iterator, bool>
@@ -1088,14 +1077,15 @@ public:
             {return __tree_.__insert_unique(__p.__i_, __v);}
 
 #if _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES)
+    // TODO(EricWF): These functions are C++17 only but they should probably
+    // be exposed in C++11.
     _LIBCPP_INLINE_VISIBILITY
     pair<iterator, bool>
-        insert(     value_type&& __v) {return __tree_.__insert_unique(_VSTD::forward<value_type>(__v));}
+    insert(value_type&& __v) {return __tree_.__insert_unique(_VSTD::move(__v));}
 
     _LIBCPP_INLINE_VISIBILITY
-    iterator
-        insert(const_iterator __p,       value_type&& __v)
-            {return __tree_.__insert_unique(__p.__i_, _VSTD::forward<value_type>(__v));}
+    iterator insert(const_iterator __p,  value_type&& __v)
+    {return __tree_.__insert_unique(__p.__i_, _VSTD::move(__v));}
 #endif
 
     template <class _InputIterator>
@@ -1331,16 +1321,10 @@ private:
     typedef __map_node_destructor<__node_allocator> _Dp;
     typedef unique_ptr<__node, _Dp> __node_holder;
 
-#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
-    __node_holder __construct_node();
-    template <class _A0>
-        __node_holder __construct_node(_A0&& __a0);
+#ifndef _LIBCPP_CXX03_LANG
     __node_holder __construct_node_with_key(key_type&& __k);
-#ifndef _LIBCPP_HAS_NO_VARIADICS
-    template <class _A0, class _A1, class ..._Args>
-        __node_holder __construct_node(_A0&& __a0, _A1&& __a1, _Args&& ...__args);
-#endif  // _LIBCPP_HAS_NO_VARIADICS
 #endif
+
     __node_holder __construct_node_with_key(const key_type& __k);
 
     __node_base_pointer const&
@@ -1401,7 +1385,7 @@ map<_Key, _Tp, _Compare, _Allocator>::__
     return __parent->__left_;
 }
 
-#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
+#ifndef _LIBCPP_CXX03_LANG
 
 template <class _Key, class _Tp, class _Compare, class _Allocator>
 map<_Key, _Tp, _Compare, _Allocator>::map(map&& __m, const allocator_type& __a)
@@ -1412,35 +1396,10 @@ map<_Key, _Tp, _Compare, _Allocator>::ma
         const_iterator __e = cend();
         while (!__m.empty())
             __tree_.__insert_unique(__e.__i_,
-                    _VSTD::move(__m.__tree_.remove(__m.begin().__i_)->__value_));
+                    _VSTD::move(__m.__tree_.remove(__m.begin().__i_)->__value_.__nc));
     }
 }
 
-template <class _Key, class _Tp, class _Compare, class _Allocator>
-typename map<_Key, _Tp, _Compare, _Allocator>::__node_holder
-map<_Key, _Tp, _Compare, _Allocator>::__construct_node()
-{
-    __node_allocator& __na = __tree_.__node_alloc();
-    __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na));
-    __node_traits::construct(__na, _VSTD::addressof(__h->__value_.__cc.first));
-    __h.get_deleter().__first_constructed = true;
-    __node_traits::construct(__na, _VSTD::addressof(__h->__value_.__cc.second));
-    __h.get_deleter().__second_constructed = true;
-    return __h;
-}
-
-template <class _Key, class _Tp, class _Compare, class _Allocator>
-template <class _A0>
-typename map<_Key, _Tp, _Compare, _Allocator>::__node_holder
-map<_Key, _Tp, _Compare, _Allocator>::__construct_node(_A0&& __a0)
-{
-    __node_allocator& __na = __tree_.__node_alloc();
-    __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na));
-    __node_traits::construct(__na, _VSTD::addressof(__h->__value_), _VSTD::forward<_A0>(__a0));
-    __h.get_deleter().__first_constructed = true;
-    __h.get_deleter().__second_constructed = true;
-    return __h;
-}
 
 template <class _Key, class _Tp, class _Compare, class _Allocator>
 typename map<_Key, _Tp, _Compare, _Allocator>::__node_holder
@@ -1455,26 +1414,7 @@ map<_Key, _Tp, _Compare, _Allocator>::__
     return __h;
 }
 
-#ifndef _LIBCPP_HAS_NO_VARIADICS
-
-template <class _Key, class _Tp, class _Compare, class _Allocator>
-template <class _A0, class _A1, class ..._Args>
-typename map<_Key, _Tp, _Compare, _Allocator>::__node_holder
-map<_Key, _Tp, _Compare, _Allocator>::__construct_node(_A0&& __a0, _A1&& __a1, _Args&& ...__args)
-{
-    __node_allocator& __na = __tree_.__node_alloc();
-    __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na));
-    __node_traits::construct(__na, _VSTD::addressof(__h->__value_),
-                             _VSTD::forward<_A0>(__a0), _VSTD::forward<_A1>(__a1),
-                             _VSTD::forward<_Args>(__args)...);
-    __h.get_deleter().__first_constructed = true;
-    __h.get_deleter().__second_constructed = true;
-    return __h;
-}
-
-#endif  // _LIBCPP_HAS_NO_VARIADICS
-
-#endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
+#endif  // !_LIBCPP_CXX03_LANG
 
 template <class _Key, class _Tp, class _Compare, class _Allocator>
 typename map<_Key, _Tp, _Compare, _Allocator>::__node_holder
@@ -1551,34 +1491,6 @@ map<_Key, _Tp, _Compare, _Allocator>::at
     return static_cast<__node_pointer>(__child)->__value_.__cc.second;
 }
 
-#if !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS)
-
-template <class _Key, class _Tp, class _Compare, class _Allocator>
-template <class ..._Args>
-pair<typename map<_Key, _Tp, _Compare, _Allocator>::iterator, bool>
-map<_Key, _Tp, _Compare, _Allocator>::emplace(_Args&& ...__args)
-{
-    __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...);
-    pair<iterator, bool> __r = __tree_.__node_insert_unique(__h.get());
-    if (__r.second)
-        __h.release();
-    return __r;
-}
-
-template <class _Key, class _Tp, class _Compare, class _Allocator>
-template <class ..._Args>
-typename map<_Key, _Tp, _Compare, _Allocator>::iterator
-map<_Key, _Tp, _Compare, _Allocator>::emplace_hint(const_iterator __p,
-                                                   _Args&& ...__args)
-{
-    __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...);
-    iterator __r = __tree_.__node_insert_unique(__p.__i_, __h.get());
-    if (__r.__i_.__ptr_ == __h.get())
-        __h.release();
-    return __r;
-}
-
-#endif  // !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS)
 
 template <class _Key, class _Tp, class _Compare, class _Allocator>
 inline _LIBCPP_INLINE_VISIBILITY
@@ -1876,18 +1788,19 @@ public:
     value_compare  value_comp() const
         {return value_compare(__tree_.value_comp().key_comp());}
 
-#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
-#ifndef _LIBCPP_HAS_NO_VARIADICS
+#ifndef _LIBCPP_CXX03_LANG
 
     template <class ..._Args>
-        iterator
-        emplace(_Args&& ...__args);
+    _LIBCPP_INLINE_VISIBILITY
+    iterator emplace(_Args&& ...__args) {
+        return __tree_.__emplace_multi(_VSTD::forward<_Args>(__args)...);
+    }
 
     template <class ..._Args>
-        iterator
-        emplace_hint(const_iterator __p, _Args&& ...__args);
-
-#endif  // _LIBCPP_HAS_NO_VARIADICS
+    _LIBCPP_INLINE_VISIBILITY
+    iterator emplace_hint(const_iterator __p, _Args&& ...__args) {
+        return __tree_.__emplace_hint_multi(__p.__i_, _VSTD::forward<_Args>(__args)...);
+    }
 
     template <class _Pp,
               class = typename enable_if<is_constructible<value_type, _Pp>::value>::type>
@@ -1901,7 +1814,7 @@ public:
         iterator insert(const_iterator __pos, _Pp&& __p)
             {return __tree_.__insert_multi(__pos.__i_, _VSTD::forward<_Pp>(__p));}
 
-#endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
+#endif  // _LIBCPP_CXX03_LANG
 
     _LIBCPP_INLINE_VISIBILITY
     iterator insert(const value_type& __v) {return __tree_.__insert_multi(__v);}
@@ -1911,12 +1824,15 @@ public:
             {return __tree_.__insert_multi(__p.__i_, __v);}
 
 #if _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES)
+    // TODO(EricWF): These functions are C++17 only but they should probably
+    // be exposed in C++11.
     _LIBCPP_INLINE_VISIBILITY
-    iterator insert( value_type&& __v) {return __tree_.__insert_multi(_VSTD::forward<value_type>(__v));}
+    iterator insert(value_type&& __v)
+        {return __tree_.__insert_multi(_VSTD::move(__v));}
 
     _LIBCPP_INLINE_VISIBILITY
     iterator insert(const_iterator __p, value_type&& __v)
-            {return __tree_.__insert_multi(__p.__i_, _VSTD::forward<value_type>(__v));}
+        {return __tree_.__insert_multi(__p.__i_, _VSTD::move(__v));}
 #endif
 
     template <class _InputIterator>
@@ -2035,21 +1951,9 @@ private:
 
     typedef __map_node_destructor<__node_allocator> _Dp;
     typedef unique_ptr<__node, _Dp> __node_holder;
-
-#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
-    __node_holder __construct_node();
-    template <class _A0>
-        __node_holder
-         __construct_node(_A0&& __a0);
-#ifndef _LIBCPP_HAS_NO_VARIADICS
-    template <class _A0, class _A1, class ..._Args>
-        __node_holder __construct_node(_A0&& __a0, _A1&& __a1, _Args&& ...__args);
-#endif  // _LIBCPP_HAS_NO_VARIADICS
-#endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
 };
 
-#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
-
+#ifndef _LIBCPP_CXX03_LANG
 template <class _Key, class _Tp, class _Compare, class _Allocator>
 multimap<_Key, _Tp, _Compare, _Allocator>::multimap(multimap&& __m, const allocator_type& __a)
     : __tree_(_VSTD::move(__m.__tree_), __a)
@@ -2059,82 +1963,10 @@ multimap<_Key, _Tp, _Compare, _Allocator
         const_iterator __e = cend();
         while (!__m.empty())
             __tree_.__insert_multi(__e.__i_,
-                    _VSTD::move(__m.__tree_.remove(__m.begin().__i_)->__value_));
+                    _VSTD::move(__m.__tree_.remove(__m.begin().__i_)->__value_.__nc));
     }
 }
-
-template <class _Key, class _Tp, class _Compare, class _Allocator>
-typename multimap<_Key, _Tp, _Compare, _Allocator>::__node_holder
-multimap<_Key, _Tp, _Compare, _Allocator>::__construct_node()
-{
-    __node_allocator& __na = __tree_.__node_alloc();
-    __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na));
-    __node_traits::construct(__na, _VSTD::addressof(__h->__value_.__cc.first));
-    __h.get_deleter().__first_constructed = true;
-    __node_traits::construct(__na, _VSTD::addressof(__h->__value_.__cc.second));
-    __h.get_deleter().__second_constructed = true;
-    return __h;
-}
-
-template <class _Key, class _Tp, class _Compare, class _Allocator>
-template <class _A0>
-typename multimap<_Key, _Tp, _Compare, _Allocator>::__node_holder
-multimap<_Key, _Tp, _Compare, _Allocator>::__construct_node(_A0&& __a0)
-{
-    __node_allocator& __na = __tree_.__node_alloc();
-    __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na));
-    __node_traits::construct(__na, _VSTD::addressof(__h->__value_), _VSTD::forward<_A0>(__a0));
-    __h.get_deleter().__first_constructed = true;
-    __h.get_deleter().__second_constructed = true;
-    return __h;
-}
-
-#ifndef _LIBCPP_HAS_NO_VARIADICS
-
-template <class _Key, class _Tp, class _Compare, class _Allocator>
-template <class _A0, class _A1, class ..._Args>
-typename multimap<_Key, _Tp, _Compare, _Allocator>::__node_holder
-multimap<_Key, _Tp, _Compare, _Allocator>::__construct_node(_A0&& __a0, _A1&& __a1, _Args&& ...__args)
-{
-    __node_allocator& __na = __tree_.__node_alloc();
-    __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na));
-    __node_traits::construct(__na, _VSTD::addressof(__h->__value_),
-                             _VSTD::forward<_A0>(__a0), _VSTD::forward<_A1>(__a1),
-                             _VSTD::forward<_Args>(__args)...);
-    __h.get_deleter().__first_constructed = true;
-    __h.get_deleter().__second_constructed = true;
-    return __h;
-}
-
-#endif  // _LIBCPP_HAS_NO_VARIADICS
-#endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
-
-#if !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS)
-
-template <class _Key, class _Tp, class _Compare, class _Allocator>
-template <class ..._Args>
-typename multimap<_Key, _Tp, _Compare, _Allocator>::iterator
-multimap<_Key, _Tp, _Compare, _Allocator>::emplace(_Args&& ...__args)
-{
-    __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...);
-    iterator __r = __tree_.__node_insert_multi(__h.get());
-    __h.release();
-    return __r;
-}
-
-template <class _Key, class _Tp, class _Compare, class _Allocator>
-template <class ..._Args>
-typename multimap<_Key, _Tp, _Compare, _Allocator>::iterator
-multimap<_Key, _Tp, _Compare, _Allocator>::emplace_hint(const_iterator __p,
-                                                        _Args&& ...__args)
-{
-    __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...);
-    iterator __r = __tree_.__node_insert_multi(__p.__i_, __h.get());
-    __h.release();
-    return __r;
-}
-
-#endif  // !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS)
+#endif
 
 template <class _Key, class _Tp, class _Compare, class _Allocator>
 inline _LIBCPP_INLINE_VISIBILITY

Added: libcxx/trunk/test/std/containers/associative/map/map.modifiers/insert_allocator_requirements.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/containers/associative/map/map.modifiers/insert_allocator_requirements.pass.cpp?rev=264986&view=auto
==============================================================================
--- libcxx/trunk/test/std/containers/associative/map/map.modifiers/insert_allocator_requirements.pass.cpp (added)
+++ libcxx/trunk/test/std/containers/associative/map/map.modifiers/insert_allocator_requirements.pass.cpp Wed Mar 30 21:15:15 2016
@@ -0,0 +1,137 @@
+//===----------------------------------------------------------------------===//
+//
+//                     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.
+//
+//===----------------------------------------------------------------------===//
+
+// <map>
+
+// class map
+
+// insert(...);
+
+// UNSUPPORTED: c++98, c++03
+
+#include <map>
+#include <iostream>
+#include <cassert>
+
+#include "test_macros.h"
+#include "count_new.hpp"
+#include "container_test_types.h"
+
+template <class Arg>
+void PrintInfo(int line, Arg&& arg)
+{
+  std::cout << "In " << __FILE__ << ":" << line << ":\n    " << arg << "\n" << std::endl;
+}
+#define PRINT(msg) PrintInfo(__LINE__, msg)
+
+template <class Container>
+void testContainerInsert()
+{
+  typedef typename Container::value_type ValueTp;
+  typedef Container C;
+  typedef std::pair<typename C::iterator, bool> R;
+  ConstructController* cc = getConstructController();
+  cc->reset();
+  {
+    PRINT("Testing C::insert(const value_type&)");
+    Container c;
+    const ValueTp v(42, 1);
+    cc->expect<const ValueTp&>();
+    assert(c.insert(v).second);
+    assert(!cc->unchecked());
+    {
+      DisableAllocationGuard g;
+      const ValueTp v2(42, 1);
+      assert(c.insert(v2).second == false);
+    }
+  }
+  {
+    PRINT("Testing C::insert(value_type&)");
+    Container c;
+    ValueTp v(42, 1);
+    cc->expect<const ValueTp&>();
+    assert(c.insert(v).second);
+    assert(!cc->unchecked());
+    {
+      DisableAllocationGuard g;
+      ValueTp v2(42, 1);
+      assert(c.insert(v2).second == false);
+    }
+  }
+  {
+    PRINT("Testing C::insert(value_type&&)");
+    Container c;
+    ValueTp v(42, 1);
+    cc->expect<ValueTp&&>();
+    assert(c.insert(std::move(v)).second);
+    assert(!cc->unchecked());
+    {
+      DisableAllocationGuard g;
+      ValueTp v2(42, 1);
+      assert(c.insert(std::move(v2)).second == false);
+    }
+  }
+  {
+    PRINT("Testing C::insert(std::initializer_list<ValueTp>)");
+    Container c;
+    std::initializer_list<ValueTp> il = { ValueTp(1, 1), ValueTp(2, 1) };
+    cc->expect<ValueTp const&>(2);
+    c.insert(il);
+    assert(!cc->unchecked());
+    {
+      DisableAllocationGuard g;
+      c.insert(il);
+    }
+  }
+  {
+    PRINT("Testing C::insert(Iter, Iter) for *Iter = value_type const&");
+    Container c;
+    const ValueTp ValueList[] = { ValueTp(1, 1), ValueTp(2, 1), ValueTp(3, 1) };
+    cc->expect<ValueTp const&>(3);
+    c.insert(std::begin(ValueList), std::end(ValueList));
+    assert(!cc->unchecked());
+    {
+      DisableAllocationGuard g;
+      c.insert(std::begin(ValueList), std::end(ValueList));
+    }
+  }
+  {
+    PRINT("Testing C::insert(Iter, Iter) for *Iter = value_type&&");
+    Container c;
+    ValueTp ValueList[] = { ValueTp(1, 1), ValueTp(2, 1) , ValueTp(3, 1) };
+    cc->expect<ValueTp&&>(3);
+    c.insert(std::move_iterator<ValueTp*>(std::begin(ValueList)),
+             std::move_iterator<ValueTp*>(std::end(ValueList)));
+    assert(!cc->unchecked());
+    {
+      DisableAllocationGuard g;
+      ValueTp ValueList2[] = { ValueTp(1, 1), ValueTp(2, 1) , ValueTp(3, 1) };
+      c.insert(std::move_iterator<ValueTp*>(std::begin(ValueList2)),
+               std::move_iterator<ValueTp*>(std::end(ValueList2)));
+    }
+  }
+  {
+    PRINT("Testing C::insert(Iter, Iter) for *Iter = value_type&");
+    Container c;
+    ValueTp ValueList[] = { ValueTp(1, 1), ValueTp(2, 1) , ValueTp(3, 1) };
+    cc->expect<ValueTp const&>(3);
+    c.insert(std::begin(ValueList), std::end(ValueList));
+    assert(!cc->unchecked());
+    {
+      DisableAllocationGuard g;
+      c.insert(std::begin(ValueList), std::end(ValueList));
+    }
+  }
+}
+
+
+int main()
+{
+  testContainerInsert<TCT::map<> >();
+}

Added: libcxx/trunk/test/std/containers/associative/multimap/multimap.modifiers/insert_allocator_requirements.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/containers/associative/multimap/multimap.modifiers/insert_allocator_requirements.pass.cpp?rev=264986&view=auto
==============================================================================
--- libcxx/trunk/test/std/containers/associative/multimap/multimap.modifiers/insert_allocator_requirements.pass.cpp (added)
+++ libcxx/trunk/test/std/containers/associative/multimap/multimap.modifiers/insert_allocator_requirements.pass.cpp Wed Mar 30 21:15:15 2016
@@ -0,0 +1,103 @@
+//===----------------------------------------------------------------------===//
+//
+//                     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.
+//
+//===----------------------------------------------------------------------===//
+
+// <map>
+
+// class multimap
+
+// insert(...)
+
+// UNSUPPORTED: c++98, c++03
+
+#include <map>
+#include <iostream>
+#include <cassert>
+
+#include "test_macros.h"
+#include "count_new.hpp"
+#include "container_test_types.h"
+
+template <class Arg>
+void PrintInfo(int line, Arg&& arg)
+{
+  std::cout << "In " << __FILE__ << ":" << line << ":\n    " << arg << "\n" << std::endl;
+}
+#define PRINT(msg) PrintInfo(__LINE__, msg)
+
+template <class Container>
+void testContainerInsert()
+{
+  typedef typename Container::value_type ValueTp;
+  typedef Container C;
+  ConstructController* cc = getConstructController();
+  cc->reset();
+  {
+    PRINT("Testing C::insert(const value_type&)");
+    Container c;
+    const ValueTp v(42, 1);
+    cc->expect<const ValueTp&>();
+    c.insert(v);
+    assert(!cc->unchecked());
+  }
+  {
+    PRINT("Testing C::insert(value_type&)");
+    Container c;
+    ValueTp v(42, 1);
+    cc->expect<ValueTp&>();
+    c.insert(v);
+    assert(!cc->unchecked());
+  }
+  {
+    PRINT("Testing C::insert(value_type&&)");
+    Container c;
+    ValueTp v(42, 1);
+    cc->expect<ValueTp&&>();
+    c.insert(std::move(v));
+    assert(!cc->unchecked());
+  }
+  {
+    PRINT("Testing C::insert(std::initializer_list<ValueTp>)");
+    Container c;
+    std::initializer_list<ValueTp> il = { ValueTp(1, 1), ValueTp(2, 1) };
+    cc->expect<ValueTp const&>(2);
+    c.insert(il);
+    assert(!cc->unchecked());
+  }
+  {
+    PRINT("Testing C::insert(Iter, Iter) for *Iter = value_type const&");
+    Container c;
+    const ValueTp ValueList[] = { ValueTp(1, 1), ValueTp(2, 1), ValueTp(3, 1) };
+    cc->expect<ValueTp const&>(3);
+    c.insert(std::begin(ValueList), std::end(ValueList));
+    assert(!cc->unchecked());
+  }
+  {
+    PRINT("Testing C::insert(Iter, Iter) for *Iter = value_type&&");
+    Container c;
+    ValueTp ValueList[] = { ValueTp(1, 1), ValueTp(2, 1) , ValueTp(3, 1) };
+    cc->expect<ValueTp&&>(3);
+    c.insert(std::move_iterator<ValueTp*>(std::begin(ValueList)),
+             std::move_iterator<ValueTp*>(std::end(ValueList)));
+    assert(!cc->unchecked());
+  }
+  {
+    PRINT("Testing C::insert(Iter, Iter) for *Iter = value_type&");
+    Container c;
+    ValueTp ValueList[] = { ValueTp(1, 1), ValueTp(2, 1) , ValueTp(3, 1) };
+    cc->expect<ValueTp&>(3);
+    c.insert(std::begin(ValueList), std::end(ValueList));
+    assert(!cc->unchecked());
+  }
+}
+
+
+int main()
+{
+  testContainerInsert<TCT::multimap<> >();
+}

Added: libcxx/trunk/test/std/containers/associative/multiset/insert_allocator_requirements.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/containers/associative/multiset/insert_allocator_requirements.pass.cpp?rev=264986&view=auto
==============================================================================
--- libcxx/trunk/test/std/containers/associative/multiset/insert_allocator_requirements.pass.cpp (added)
+++ libcxx/trunk/test/std/containers/associative/multiset/insert_allocator_requirements.pass.cpp Wed Mar 30 21:15:15 2016
@@ -0,0 +1,102 @@
+//===----------------------------------------------------------------------===//
+//
+//                     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.
+//
+//===----------------------------------------------------------------------===//
+
+// <set>
+
+// class multiset
+
+// insert(...)
+
+// UNSUPPORTED: c++98, c++03
+
+#include <set>
+#include <iostream>
+#include <cassert>
+
+#include "test_macros.h"
+#include "count_new.hpp"
+#include "container_test_types.h"
+
+template <class Arg>
+void PrintInfo(int line, Arg&& arg)
+{
+  std::cout << "In " << __FILE__ << ":" << line << ":\n    " << arg << "\n" << std::endl;
+}
+#define PRINT(...) PrintInfo(__LINE__, __VA_ARGS__)
+
+template <class Container>
+void testContainerInsert()
+{
+  typedef typename Container::value_type ValueTp;
+  typedef Container C;
+  ConstructController* cc = getConstructController();
+  cc->reset();
+  {
+    PRINT("Testing C::insert(const value_type&)");
+    Container c;
+    const ValueTp v(42);
+    cc->expect<const ValueTp&>();
+    c.insert(v);
+    assert(!cc->unchecked());
+  }
+  {
+    PRINT("Testing C::insert(value_type&)");
+    Container c;
+    ValueTp v(42);
+    cc->expect<const ValueTp&>();
+    c.insert(v);
+    assert(!cc->unchecked());
+  }
+  {
+    PRINT("Testing C::insert(value_type&&)");
+    Container c;
+    ValueTp v(42);
+    cc->expect<ValueTp&&>();
+    c.insert(std::move(v));
+    assert(!cc->unchecked());
+  }
+  {
+    PRINT("Testing C::insert(std::initializer_list<ValueTp>)");
+    Container c;
+    std::initializer_list<ValueTp> il = { ValueTp(1), ValueTp(2) };
+    cc->expect<ValueTp const&>(2);
+    c.insert(il);
+    assert(!cc->unchecked());
+  }
+  {
+    PRINT("Testing C::insert(Iter, Iter) for *Iter = value_type const&");
+    Container c;
+    const ValueTp ValueList[] = { ValueTp(1), ValueTp(2), ValueTp(3) };
+    cc->expect<ValueTp const&>(3);
+    c.insert(std::begin(ValueList), std::end(ValueList));
+    assert(!cc->unchecked());
+  }
+  {
+    PRINT("Testing C::insert(Iter, Iter) for *Iter = value_type&&");
+    Container c;
+    ValueTp ValueList[] = { ValueTp(1), ValueTp(2) , ValueTp(3) };
+    cc->expect<ValueTp&&>(3);
+    c.insert(std::move_iterator<ValueTp*>(std::begin(ValueList)),
+             std::move_iterator<ValueTp*>(std::end(ValueList)));
+    assert(!cc->unchecked());
+  }
+  {
+    PRINT("Testing C::insert(Iter, Iter) for *Iter = value_type&");
+    Container c;
+    ValueTp ValueList[] = { ValueTp(1), ValueTp(2) , ValueTp(3) };
+    cc->expect<ValueTp&>(3);
+    c.insert(std::begin(ValueList), std::end(ValueList));
+    assert(!cc->unchecked());
+  }
+}
+
+int main()
+{
+  testContainerInsert<TCT::multiset<> >();
+}

Added: libcxx/trunk/test/std/containers/associative/set/insert_allocator_requirements.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/containers/associative/set/insert_allocator_requirements.pass.cpp?rev=264986&view=auto
==============================================================================
--- libcxx/trunk/test/std/containers/associative/set/insert_allocator_requirements.pass.cpp (added)
+++ libcxx/trunk/test/std/containers/associative/set/insert_allocator_requirements.pass.cpp Wed Mar 30 21:15:15 2016
@@ -0,0 +1,137 @@
+//===----------------------------------------------------------------------===//
+//
+//                     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.
+//
+//===----------------------------------------------------------------------===//
+
+// <set>
+
+// class set
+
+// insert(...)
+
+// UNSUPPORTED: c++98, c++03
+
+#include <set>
+#include <iostream>
+#include <cassert>
+
+#include "test_macros.h"
+#include "count_new.hpp"
+#include "container_test_types.h"
+
+template <class Arg>
+void PrintInfo(int line, Arg&& arg)
+{
+  std::cout << "In " << __FILE__ << ":" << line << ":\n    " << arg << "\n" << std::endl;
+}
+#define PRINT(msg) PrintInfo(__LINE__, msg)
+
+template <class Container>
+void testContainerInsert()
+{
+  typedef typename Container::value_type ValueTp;
+  typedef Container C;
+  typedef std::pair<typename C::iterator, bool> R;
+  ConstructController* cc = getConstructController();
+  cc->reset();
+  {
+    PRINT("Testing C::insert(const value_type&)");
+    Container c;
+    const ValueTp v(42);
+    cc->expect<const ValueTp&>();
+    assert(c.insert(v).second);
+    assert(!cc->unchecked());
+    {
+      DisableAllocationGuard g;
+      const ValueTp v2(42);
+      assert(c.insert(v2).second == false);
+    }
+  }
+  {
+    PRINT("Testing C::insert(value_type&)");
+    Container c;
+    ValueTp v(42);
+    cc->expect<const ValueTp&>();
+    assert(c.insert(v).second);
+    assert(!cc->unchecked());
+    {
+      DisableAllocationGuard g;
+      ValueTp v2(42);
+      assert(c.insert(v2).second == false);
+    }
+  }
+  {
+    PRINT("Testing C::insert(value_type&&)");
+    Container c;
+    ValueTp v(42);
+    cc->expect<ValueTp&&>();
+    assert(c.insert(std::move(v)).second);
+    assert(!cc->unchecked());
+    {
+      DisableAllocationGuard g;
+      ValueTp v2(42);
+      assert(c.insert(std::move(v2)).second == false);
+    }
+  }
+  {
+    PRINT("Testing C::insert(std::initializer_list<ValueTp>)");
+    Container c;
+    std::initializer_list<ValueTp> il = { ValueTp(1), ValueTp(2) };
+    cc->expect<ValueTp const&>(2);
+    c.insert(il);
+    assert(!cc->unchecked());
+    {
+      DisableAllocationGuard g;
+      c.insert(il);
+    }
+  }
+  {
+    PRINT("Testing C::insert(Iter, Iter) for *Iter = value_type const&");
+    Container c;
+    const ValueTp ValueList[] = { ValueTp(1), ValueTp(2), ValueTp(3) };
+    cc->expect<ValueTp const&>(3);
+    c.insert(std::begin(ValueList), std::end(ValueList));
+    assert(!cc->unchecked());
+    {
+      DisableAllocationGuard g;
+      c.insert(std::begin(ValueList), std::end(ValueList));
+    }
+  }
+  {
+    PRINT("Testing C::insert(Iter, Iter) for *Iter = value_type&&");
+    Container c;
+    ValueTp ValueList[] = { ValueTp(1), ValueTp(2) , ValueTp(3) };
+    cc->expect<ValueTp&&>(3);
+    c.insert(std::move_iterator<ValueTp*>(std::begin(ValueList)),
+             std::move_iterator<ValueTp*>(std::end(ValueList)));
+    assert(!cc->unchecked());
+    {
+      DisableAllocationGuard g;
+      ValueTp ValueList2[] = { ValueTp(1), ValueTp(2) , ValueTp(3) };
+      c.insert(std::move_iterator<ValueTp*>(std::begin(ValueList2)),
+               std::move_iterator<ValueTp*>(std::end(ValueList2)));
+    }
+  }
+  {
+    PRINT("Testing C::insert(Iter, Iter) for *Iter = value_type&");
+    Container c;
+    ValueTp ValueList[] = { ValueTp(1), ValueTp(2) , ValueTp(3) };
+    cc->expect<ValueTp const&>(3);
+    c.insert(std::begin(ValueList), std::end(ValueList));
+    assert(!cc->unchecked());
+    {
+      DisableAllocationGuard g;
+      c.insert(std::begin(ValueList), std::end(ValueList));
+    }
+  }
+}
+
+
+int main()
+{
+  testContainerInsert<TCT::set<> >();
+}




More information about the cfe-commits mailing list