[libcxx] r261416 - Cleanup node-type handling in the associative containers.

Eric Fiselier via cfe-commits cfe-commits at lists.llvm.org
Fri Feb 19 21:28:30 PST 2016


Author: ericwf
Date: Fri Feb 19 23:28:30 2016
New Revision: 261416

URL: http://llvm.org/viewvc/llvm-project?rev=261416&view=rev
Log:
Cleanup node-type handling in the associative containers.

This patch is very similar to r260431.

This patch is the first in a series of patches that's meant to better
support map. map has a special "value_type" that
differs from pair<const Key, Value>. In order to meet the EmplaceConstructible
and CopyInsertable requirements we need to teach __tree about this
special value_type.

This patch creates a "__tree_node_types" traits class that contains
all of the typedefs needed by the associative containers and their iterators.
These typedefs include ones for each node type and  node pointer type,
as well as special typedefs for "map"'s value type.

Although the associative containers already supported incomplete types, this
patch makes it official by adding tests.

This patch will be followed up shortly with various cleanups within __tree and
fixes for various map bugs and problems.

Added:
    libcxx/trunk/test/libcxx/containers/associative/
    libcxx/trunk/test/libcxx/containers/associative/tree_key_value_traits.pass.cpp
    libcxx/trunk/test/std/containers/associative/iterator_types.pass.cpp
    libcxx/trunk/test/std/containers/associative/map/incomplete_type.pass.cpp
    libcxx/trunk/test/std/containers/associative/multimap/incomplete_type.pass.cpp
    libcxx/trunk/test/std/containers/associative/multiset/incomplete_type.pass.cpp
    libcxx/trunk/test/std/containers/associative/set/incomplete_type.pass.cpp
Modified:
    libcxx/trunk/include/__tree
    libcxx/trunk/include/map

Modified: libcxx/trunk/include/__tree
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/__tree?rev=261416&r1=261415&r2=261416&view=diff
==============================================================================
--- libcxx/trunk/include/__tree (original)
+++ libcxx/trunk/include/__tree Fri Feb 19 23:28:30 2016
@@ -29,6 +29,22 @@ template <class _Tp, class _NodePtr, cla
 template <class _Tp, class _ConstNodePtr, class _DiffType>
     class _LIBCPP_TYPE_VIS_ONLY __tree_const_iterator;
 
+template <class _Pointer> class __tree_end_node;
+template <class _VoidPtr> class __tree_node_base;
+template <class _Tp, class _VoidPtr> class __tree_node;
+
+#ifndef _LIBCPP_CXX03_LANG
+template <class _Key, class _Value>
+union __value_type;
+#else
+template <class _Key, class _Value>
+struct __value_type;
+#endif
+
+template <class _Allocator> class __map_node_destructor;
+template <class _TreeIterator> class _LIBCPP_TYPE_VIS_ONLY __map_iterator;
+template <class _TreeIterator> class _LIBCPP_TYPE_VIS_ONLY __map_const_iterator;
+
 /*
 
 _NodePtr algorithms
@@ -494,14 +510,12 @@ __tree_remove(_NodePtr __root, _NodePtr
     }
 }
 
-template <class _Allocator> class __map_node_destructor;
-
 template <class _Allocator>
 class __tree_node_destructor
 {
     typedef _Allocator                                      allocator_type;
     typedef allocator_traits<allocator_type>                __alloc_traits;
-    typedef typename __alloc_traits::value_type::value_type value_type;
+
 public:
     typedef typename __alloc_traits::pointer                pointer;
 private:
@@ -531,6 +545,92 @@ public:
     template <class> friend class __map_node_destructor;
 };
 
+// node traits
+
+template <class _Tp>
+struct __tree_key_value_types {
+  typedef _Tp key_type;
+  typedef _Tp __node_value_type;
+  typedef _Tp __container_value_type;
+  static const bool __is_map = false;
+};
+
+template <class _Key, class _Tp>
+struct __tree_key_value_types<__value_type<_Key, _Tp> > {
+  typedef _Key                                         key_type;
+  typedef _Tp                                          mapped_type;
+  typedef __value_type<_Key, _Tp>                      __node_value_type;
+  typedef pair<const _Key, _Tp>                        __container_value_type;
+  typedef pair<_Key, _Tp>                              __nc_value_type;
+  typedef __container_value_type                       __map_value_type;
+  static const bool __is_map = true;
+};
+
+template <class _VoidPtr>
+struct __tree_node_base_types {
+  typedef _VoidPtr                                               __void_pointer;
+
+  typedef __tree_node_base<__void_pointer>                      __node_base_type;
+  typedef typename __rebind_pointer<_VoidPtr, __node_base_type>::type
+                                                             __node_base_pointer;
+
+  typedef __tree_end_node<__node_base_pointer>                  __end_node_type;
+  typedef typename __rebind_pointer<_VoidPtr, __end_node_type>::type
+                                                             __end_node_pointer;
+private:
+  static_assert((is_same<typename pointer_traits<_VoidPtr>::element_type, void>::value),
+                  "_VoidPtr does not point to unqualified void type");
+};
+
+template <class _Tp, class _AllocPtr, class _KVTypes = __tree_key_value_types<_Tp>,
+         bool = _KVTypes::__is_map>
+struct __tree_map_pointer_types {};
+
+template <class _Tp, class _AllocPtr, class _KVTypes>
+struct __tree_map_pointer_types<_Tp, _AllocPtr, _KVTypes, true> {
+  typedef typename _KVTypes::__map_value_type   _Mv;
+  typedef typename __rebind_pointer<_AllocPtr, _Mv>::type
+                                                       __map_value_type_pointer;
+  typedef typename __rebind_pointer<_AllocPtr, const _Mv>::type
+                                                 __const_map_value_type_pointer;
+};
+
+template <class _NodePtr, class _NodeT = typename pointer_traits<_NodePtr>::element_type>
+struct __tree_node_types;
+
+template <class _NodePtr, class _Tp, class _VoidPtr>
+struct __tree_node_types<_NodePtr, __tree_node<_Tp, _VoidPtr> >
+    : public __tree_node_base_types<_VoidPtr>,
+             __tree_key_value_types<_Tp>,
+             __tree_map_pointer_types<_Tp, _VoidPtr>
+{
+  typedef __tree_node_base_types<_VoidPtr> __base;
+  typedef __tree_key_value_types<_Tp>      __key_base;
+  typedef __tree_map_pointer_types<_Tp, _VoidPtr> __map_pointer_base;
+public:
+
+  typedef typename pointer_traits<_NodePtr>::element_type       __node_type;
+  typedef _NodePtr                                              __node_pointer;
+
+  typedef _Tp                                                 __node_value_type;
+  typedef typename __rebind_pointer<_VoidPtr, __node_value_type>::type
+                                                      __node_value_type_pointer;
+  typedef typename __rebind_pointer<_VoidPtr, const __node_value_type>::type
+                                                __const_node_value_type_pointer;
+private:
+    static_assert(!is_const<__node_type>::value,
+                "_NodePtr should never be a pointer to const");
+    static_assert((is_same<typename __rebind_pointer<_VoidPtr, __node_type>::type,
+                          _NodePtr>::value), "_VoidPtr does not rebind to _NodePtr.");
+};
+
+template <class _ValueTp, class _VoidPtr>
+struct __make_tree_node_types {
+  typedef typename __rebind_pointer<_VoidPtr, __tree_node<_ValueTp, _VoidPtr> >::type
+                                                                        _NodePtr;
+  typedef __tree_node_types<_NodePtr> type;
+};
+
 // node
 
 template <class _Pointer>
@@ -546,18 +646,14 @@ public:
 
 template <class _VoidPtr>
 class __tree_node_base
-    : public __tree_end_node
-             <
-                typename __rebind_pointer<_VoidPtr, __tree_node_base<_VoidPtr> >::type
-             >
+    : public __tree_node_base_types<_VoidPtr>::__end_node_type
 {
+    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 __rebind_pointer<_VoidPtr, __tree_node_base>::type pointer;
-    typedef typename __rebind_pointer<_VoidPtr, const __tree_node_base>::type const_pointer;
-
-    typedef __tree_end_node<pointer> base;
+    typedef typename _NodeBaseTypes::__node_base_pointer pointer;
 
     pointer __right_;
     pointer __parent_;
@@ -573,10 +669,9 @@ class __tree_node
     : public __tree_node_base<_VoidPtr>
 {
 public:
-    typedef __tree_node_base<_VoidPtr> base;
-    typedef _Tp value_type;
+    typedef _Tp __node_value_type;
 
-    value_type __value_;
+    __node_value_type __value_;
 
 #if !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS)
     template <class ..._Args>
@@ -585,29 +680,27 @@ public:
             : __value_(_VSTD::forward<_Args>(__args)...) {}
 #else  // !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS)
     _LIBCPP_INLINE_VISIBILITY
-    explicit __tree_node(const value_type& __v)
+    explicit __tree_node(const __node_value_type& __v)
             : __value_(__v) {}
 #endif  // !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS)
 };
 
-template <class _TreeIterator> class _LIBCPP_TYPE_VIS_ONLY __map_iterator;
-template <class _TreeIterator> class _LIBCPP_TYPE_VIS_ONLY __map_const_iterator;
-
 template <class _Tp, class _NodePtr, class _DiffType>
 class _LIBCPP_TYPE_VIS_ONLY __tree_iterator
 {
-    typedef _NodePtr                                              __node_pointer;
-    typedef typename pointer_traits<__node_pointer>::element_type __node;
+    typedef __tree_node_types<_NodePtr>                     _NodeTypes;
+    typedef _NodePtr                                        __node_pointer;
+    typedef typename _NodeTypes::__node_base_pointer        __node_base_pointer;
+    typedef pointer_traits<__node_pointer> __pointer_traits;
 
     __node_pointer __ptr_;
 
-    typedef pointer_traits<__node_pointer> __pointer_traits;
 public:
-    typedef bidirectional_iterator_tag iterator_category;
-    typedef _Tp                        value_type;
-    typedef _DiffType                  difference_type;
-    typedef value_type&                reference;
-    typedef typename __rebind_pointer<__node_pointer, value_type>::type pointer;
+    typedef bidirectional_iterator_tag                     iterator_category;
+    typedef _Tp                                            value_type;
+    typedef _DiffType                                      difference_type;
+    typedef value_type&                                    reference;
+    typedef typename _NodeTypes::__node_value_type_pointer pointer;
 
     _LIBCPP_INLINE_VISIBILITY __tree_iterator() _NOEXCEPT
 #if _LIBCPP_STD_VER > 11
@@ -622,7 +715,7 @@ public:
     _LIBCPP_INLINE_VISIBILITY
     __tree_iterator& operator++() {
       __ptr_ = static_cast<__node_pointer>(
-          __tree_next(static_cast<typename __node::base::pointer>(__ptr_)));
+          __tree_next(static_cast<__node_base_pointer>(__ptr_)));
       return *this;
     }
     _LIBCPP_INLINE_VISIBILITY
@@ -632,7 +725,7 @@ public:
     _LIBCPP_INLINE_VISIBILITY
     __tree_iterator& operator--() {
       __ptr_ = static_cast<__node_pointer>(
-          __tree_prev(static_cast<typename __node::base::pointer>(__ptr_)));
+          __tree_prev(static_cast<__node_base_pointer>(__ptr_)));
       return *this;
     }
     _LIBCPP_INLINE_VISIBILITY
@@ -658,21 +751,22 @@ private:
     template <class, class, class> friend class _LIBCPP_TYPE_VIS_ONLY multiset;
 };
 
-template <class _Tp, class _ConstNodePtr, class _DiffType>
+template <class _Tp, class _NodePtr, class _DiffType>
 class _LIBCPP_TYPE_VIS_ONLY __tree_const_iterator
 {
-    typedef _ConstNodePtr                                         __node_pointer;
-    typedef typename pointer_traits<__node_pointer>::element_type __node;
+    typedef __tree_node_types<_NodePtr>                     _NodeTypes;
+    typedef typename _NodeTypes::__node_pointer             __node_pointer;
+    typedef typename _NodeTypes::__node_base_pointer        __node_base_pointer;
+    typedef pointer_traits<__node_pointer> __pointer_traits;
 
     __node_pointer __ptr_;
 
-    typedef pointer_traits<__node_pointer> __pointer_traits;
 public:
-    typedef bidirectional_iterator_tag       iterator_category;
-    typedef _Tp                              value_type;
-    typedef _DiffType                        difference_type;
-    typedef const value_type&                reference;
-    typedef typename __rebind_pointer<__node_pointer, const value_type>::type pointer;
+    typedef bidirectional_iterator_tag                           iterator_category;
+    typedef _Tp                                                  value_type;
+    typedef _DiffType                                            difference_type;
+    typedef const value_type&                                    reference;
+    typedef typename _NodeTypes::__const_node_value_type_pointer pointer;
 
     _LIBCPP_INLINE_VISIBILITY __tree_const_iterator() _NOEXCEPT
 #if _LIBCPP_STD_VER > 11
@@ -681,11 +775,8 @@ public:
     {}
 
 private:
-    typedef typename remove_const<__node>::type  __non_const_node;
-    typedef typename __rebind_pointer<__node_pointer, __non_const_node>::type
-        __non_const_node_pointer;
-    typedef __tree_iterator<value_type, __non_const_node_pointer, difference_type>
-                                                 __non_const_iterator;
+    typedef __tree_iterator<value_type, __node_pointer, difference_type>
+                                                           __non_const_iterator;
 public:
     _LIBCPP_INLINE_VISIBILITY
     __tree_const_iterator(__non_const_iterator __p) _NOEXCEPT
@@ -697,8 +788,6 @@ public:
 
     _LIBCPP_INLINE_VISIBILITY
     __tree_const_iterator& operator++() {
-      typedef typename __rebind_pointer<__node_pointer, typename __node::base>::type
-        __node_base_pointer;
       __ptr_ = static_cast<__node_pointer>(
           __tree_next(static_cast<__node_base_pointer>(__ptr_)));
       return *this;
@@ -710,8 +799,6 @@ public:
 
     _LIBCPP_INLINE_VISIBILITY
     __tree_const_iterator& operator--() {
-      typedef typename __rebind_pointer<__node_pointer, typename __node::base>::type
-        __node_base_pointer;
       __ptr_ = static_cast<__node_pointer>(
           __tree_prev(static_cast<__node_base_pointer>(__ptr_)));
       return *this;
@@ -747,28 +834,52 @@ public:
     typedef _Tp                                      value_type;
     typedef _Compare                                 value_compare;
     typedef _Allocator                               allocator_type;
+
+private:
     typedef allocator_traits<allocator_type>         __alloc_traits;
+    typedef typename __make_tree_node_types<value_type,
+        typename __alloc_traits::void_pointer>::type
+                                                    _NodeTypes;
+public:
+    typedef typename _NodeTypes::__node_value_type      __node_value_type;
+    typedef typename _NodeTypes::__container_value_type __container_value_type;
+
     typedef typename __alloc_traits::pointer         pointer;
     typedef typename __alloc_traits::const_pointer   const_pointer;
     typedef typename __alloc_traits::size_type       size_type;
     typedef typename __alloc_traits::difference_type difference_type;
 
-    typedef typename __alloc_traits::void_pointer  __void_pointer;
+public:
+    typedef typename _NodeTypes::__void_pointer        __void_pointer;
+
+    typedef typename _NodeTypes::__node_type           __node;
+    typedef typename _NodeTypes::__node_pointer        __node_pointer;
+    typedef typename _NodeTypes::__node_pointer        __node_const_pointer;
+
+    typedef typename _NodeTypes::__node_base_type      __node_base;
+    typedef typename _NodeTypes::__node_base_pointer   __node_base_pointer;
+    typedef typename _NodeTypes::__node_base_pointer   __node_base_const_pointer;
+
+    typedef typename _NodeTypes::__end_node_type       __end_node_t;
+    typedef typename _NodeTypes::__end_node_pointer    __end_node_ptr;
+    typedef typename _NodeTypes::__end_node_pointer    __end_node_const_ptr;
 
-    typedef __tree_node<value_type, __void_pointer> __node;
-    typedef __tree_node_base<__void_pointer>        __node_base;
     typedef typename __rebind_alloc_helper<__alloc_traits, __node>::type __node_allocator;
-    typedef allocator_traits<__node_allocator>       __node_traits;
-    typedef typename __node_traits::pointer          __node_pointer;
-    typedef typename __node_traits::pointer          __node_const_pointer;
-    typedef typename __node_base::pointer            __node_base_pointer;
-    typedef typename __node_base::pointer            __node_base_const_pointer;
+    typedef allocator_traits<__node_allocator>         __node_traits;
+
 private:
-    typedef typename __node_base::base __end_node_t;
-    typedef typename __rebind_pointer<__node_pointer, __end_node_t>::type
-        __end_node_ptr;
-    typedef __end_node_ptr __end_node_const_ptr;
+    // check for sane allocator pointer rebinding semantics. Rebinding the
+    // allocator for a new pointer type should be exactly the same as rebinding
+    // the pointer using 'pointer_traits'.
+    static_assert((is_same<__node_pointer, typename __node_traits::pointer>::value),
+                  "Allocator does not rebind pointers in a sane manner.");
+    typedef typename __rebind_alloc_helper<__node_traits, __node_base>::type
+        __node_base_allocator;
+    typedef allocator_traits<__node_base_allocator> __node_base_traits;
+    static_assert((is_same<__node_base_pointer, typename __node_base_traits::pointer>::value),
+                 "Allocator does not rebind pointers in a sane manner.");
 
+private:
     __node_pointer                                          __begin_node_;
     __compressed_pair<__end_node_t, __node_allocator>  __pair1_;
     __compressed_pair<size_type, value_compare>        __pair3_;

Modified: libcxx/trunk/include/map
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/map?rev=261416&r1=261415&r2=261416&view=diff
==============================================================================
--- libcxx/trunk/include/map (original)
+++ libcxx/trunk/include/map Fri Feb 19 23:28:30 2016
@@ -564,13 +564,11 @@ class __map_node_destructor
 {
     typedef _Allocator                          allocator_type;
     typedef allocator_traits<allocator_type>    __alloc_traits;
-    typedef typename __alloc_traits::value_type::value_type value_type;
+
 public:
     typedef typename __alloc_traits::pointer    pointer;
-private:
-    typedef typename value_type::value_type::first_type     first_type;
-    typedef typename value_type::value_type::second_type    second_type;
 
+private:
     allocator_type& __na_;
 
     __map_node_destructor& operator=(const __map_node_destructor&);
@@ -615,7 +613,7 @@ template <class _Key, class _Tp, class _
     class multimap;
 template <class _TreeIterator> class __map_const_iterator;
 
-#if __cplusplus >= 201103L
+#ifndef _LIBCPP_CXX03_LANG
 
 template <class _Key, class _Tp>
 union __value_type
@@ -697,19 +695,17 @@ struct __extract_key_value_types<__value
 template <class _TreeIterator>
 class _LIBCPP_TYPE_VIS_ONLY __map_iterator
 {
+    typedef typename _TreeIterator::_NodeTypes                   _NodeTypes;
+    typedef typename _TreeIterator::__pointer_traits             __pointer_traits;
+
     _TreeIterator __i_;
 
-    typedef typename _TreeIterator::__pointer_traits             __pointer_traits;
-    typedef typename _TreeIterator::value_type __value_type;
-    typedef typename __extract_key_value_types<__value_type>::__key_type    __key_type;
-    typedef typename __extract_key_value_types<__value_type>::__mapped_type __mapped_type;
 public:
     typedef bidirectional_iterator_tag                           iterator_category;
-    typedef pair<__key_type, __mapped_type>                      value_type;
+    typedef typename _NodeTypes::__map_value_type                value_type;
     typedef typename _TreeIterator::difference_type              difference_type;
     typedef value_type&                                          reference;
-    typedef typename __rebind_pointer<typename __pointer_traits::pointer, value_type>::type
-        pointer;
+    typedef typename _NodeTypes::__map_value_type_pointer        pointer;
 
     _LIBCPP_INLINE_VISIBILITY
     __map_iterator() _NOEXCEPT {}
@@ -758,19 +754,17 @@ public:
 template <class _TreeIterator>
 class _LIBCPP_TYPE_VIS_ONLY __map_const_iterator
 {
+    typedef typename _TreeIterator::_NodeTypes                   _NodeTypes;
+    typedef typename _TreeIterator::__pointer_traits             __pointer_traits;
+
     _TreeIterator __i_;
 
-    typedef typename _TreeIterator::__pointer_traits             __pointer_traits;
-    typedef typename _TreeIterator::value_type __value_type;
-    typedef typename __extract_key_value_types<__value_type>::__key_type    __key_type;
-    typedef typename __extract_key_value_types<__value_type>::__mapped_type __mapped_type;
 public:
     typedef bidirectional_iterator_tag                           iterator_category;
-    typedef pair<__key_type, __mapped_type>                      value_type;
+    typedef typename _NodeTypes::__map_value_type                value_type;
     typedef typename _TreeIterator::difference_type              difference_type;
     typedef const value_type&                                    reference;
-    typedef typename __rebind_pointer<typename __pointer_traits::pointer, const value_type>::type
-        pointer;
+    typedef typename _NodeTypes::__const_map_value_type_pointer  pointer;
 
     _LIBCPP_INLINE_VISIBILITY
     __map_const_iterator() _NOEXCEPT {}

Added: libcxx/trunk/test/libcxx/containers/associative/tree_key_value_traits.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/libcxx/containers/associative/tree_key_value_traits.pass.cpp?rev=261416&view=auto
==============================================================================
--- libcxx/trunk/test/libcxx/containers/associative/tree_key_value_traits.pass.cpp (added)
+++ libcxx/trunk/test/libcxx/containers/associative/tree_key_value_traits.pass.cpp Fri Feb 19 23:28:30 2016
@@ -0,0 +1,59 @@
+//===----------------------------------------------------------------------===//
+//
+//                     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.
+//
+//===----------------------------------------------------------------------===//
+
+#include <__tree>
+#include <map>
+#include <set>
+#include <type_traits>
+
+#include "test_macros.h"
+#include "min_allocator.h"
+
+void testKeyValueTrait() {
+  {
+    typedef int Tp;
+    typedef std::__tree_key_value_types<Tp> Traits;
+    static_assert((std::is_same<Traits::key_type, int>::value), "");
+    static_assert((std::is_same<Traits::__node_value_type, Tp>::value), "");
+    static_assert((std::is_same<Traits::__container_value_type, Tp>::value), "");
+    static_assert(Traits::__is_map == false, "");
+  }
+  {
+    typedef std::pair<int, int> Tp;
+    typedef std::__tree_key_value_types<Tp> Traits;
+    static_assert((std::is_same<Traits::key_type, Tp>::value), "");
+    static_assert((std::is_same<Traits::__node_value_type, Tp>::value), "");
+    static_assert((std::is_same<Traits::__container_value_type, Tp>::value), "");
+    static_assert(Traits::__is_map == false, "");
+  }
+  {
+    typedef std::pair<const int, int> Tp;
+    typedef std::__tree_key_value_types<Tp> Traits;
+    static_assert((std::is_same<Traits::key_type, Tp>::value), "");
+    static_assert((std::is_same<Traits::__node_value_type, Tp>::value), "");
+    static_assert((std::is_same<Traits::__container_value_type, Tp>::value), "");
+    static_assert(Traits::__is_map == false, "");
+  }
+  {
+    typedef std::__value_type<int, int> Tp;
+    typedef std::__tree_key_value_types<Tp> Traits;
+    static_assert((std::is_same<Traits::key_type, int>::value), "");
+    static_assert((std::is_same<Traits::mapped_type, int>::value), "");
+    static_assert((std::is_same<Traits::__node_value_type, Tp>::value), "");
+    static_assert((std::is_same<Traits::__container_value_type,
+                               std::pair<const int, int> >::value), "");
+    static_assert((std::is_same<Traits::__map_value_type,
+                               std::pair<const int, int> >::value), "");
+    static_assert(Traits::__is_map == true, "");
+  }
+}
+
+int main() {
+  testKeyValueTrait();
+}

Added: libcxx/trunk/test/std/containers/associative/iterator_types.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/containers/associative/iterator_types.pass.cpp?rev=261416&view=auto
==============================================================================
--- libcxx/trunk/test/std/containers/associative/iterator_types.pass.cpp (added)
+++ libcxx/trunk/test/std/containers/associative/iterator_types.pass.cpp Fri Feb 19 23:28:30 2016
@@ -0,0 +1,131 @@
+//===----------------------------------------------------------------------===//
+//
+//                     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.
+//
+//===----------------------------------------------------------------------===//
+
+#include <map>
+#include <set>
+#include <type_traits>
+
+#include "test_macros.h"
+#include "min_allocator.h"
+#include "test_allocator.h"
+
+
+template <class Map, class ValueTp, class PtrT, class CPtrT>
+void testMap() {
+  typedef typename Map::difference_type Diff;
+  {
+    typedef typename Map::iterator It;
+    static_assert((std::is_same<typename It::value_type, ValueTp>::value), "");
+    static_assert((std::is_same<typename It::reference, ValueTp&>::value), "");
+    static_assert((std::is_same<typename It::pointer, PtrT>::value), "");
+    static_assert((std::is_same<typename It::difference_type, Diff>::value), "");
+  }
+  {
+    typedef typename Map::const_iterator It;
+    static_assert((std::is_same<typename It::value_type, ValueTp>::value), "");
+    static_assert((std::is_same<typename It::reference, ValueTp const&>::value), "");
+    static_assert((std::is_same<typename It::pointer, CPtrT>::value), "");
+    static_assert((std::is_same<typename It::difference_type, Diff>::value), "");
+  }
+}
+
+
+template <class Set, class ValueTp, class CPtrT>
+void testSet() {
+  static_assert((std::is_same<typename Set::iterator,
+                             typename Set::const_iterator>::value), "");
+  typedef typename Set::difference_type Diff;
+  {
+    typedef typename Set::iterator It;
+    static_assert((std::is_same<typename It::value_type, ValueTp>::value), "");
+    static_assert((std::is_same<typename It::reference, ValueTp const&>::value), "");
+    static_assert((std::is_same<typename It::pointer, CPtrT>::value), "");
+    static_assert((std::is_same<typename It::difference_type, Diff>::value), "");
+
+  }
+}
+
+int main() {
+  {
+    typedef std::map<int, int> Map;
+    typedef std::pair<const int, int> ValueTp;
+    testMap<Map, ValueTp, ValueTp*, ValueTp const*>();
+  }
+  {
+    typedef std::pair<const int, int> ValueTp;
+    typedef test_allocator<ValueTp> Alloc;
+    typedef std::map<int, int, std::less<int>, Alloc> Map;
+    testMap<Map, ValueTp, ValueTp*, ValueTp const*>();
+  }
+#if TEST_STD_VER >= 11
+  {
+    typedef std::pair<const int, int> ValueTp;
+    typedef min_allocator<ValueTp> Alloc;
+    typedef std::map<int, int, std::less<int>, Alloc> Map;
+    testMap<Map, ValueTp, min_pointer<ValueTp>, min_pointer<const ValueTp>>();
+  }
+#endif
+  {
+    typedef std::multimap<int, int> Map;
+    typedef std::pair<const int, int> ValueTp;
+    testMap<Map, ValueTp, ValueTp*, ValueTp const*>();
+  }
+  {
+    typedef std::pair<const int, int> ValueTp;
+    typedef test_allocator<ValueTp> Alloc;
+    typedef std::multimap<int, int, std::less<int>, Alloc> Map;
+    testMap<Map, ValueTp, ValueTp*, ValueTp const*>();
+  }
+#if TEST_STD_VER >= 11
+  {
+    typedef std::pair<const int, int> ValueTp;
+    typedef min_allocator<ValueTp> Alloc;
+    typedef std::multimap<int, int, std::less<int>, Alloc> Map;
+    testMap<Map, ValueTp, min_pointer<ValueTp>, min_pointer<const ValueTp>>();
+  }
+#endif
+  {
+    typedef int ValueTp;
+    typedef std::set<ValueTp> Set;
+    testSet<Set, ValueTp, ValueTp const*>();
+  }
+  {
+    typedef int ValueTp;
+    typedef test_allocator<ValueTp> Alloc;
+    typedef std::set<ValueTp, std::less<ValueTp>, Alloc> Set;
+    testSet<Set, ValueTp, ValueTp const*>();
+  }
+#if TEST_STD_VER >= 11
+  {
+    typedef int ValueTp;
+    typedef min_allocator<ValueTp> Alloc;
+    typedef std::set<ValueTp, std::less<ValueTp>, Alloc> Set;
+    testSet<Set, ValueTp, min_pointer<const ValueTp>>();
+  }
+#endif
+  {
+    typedef int ValueTp;
+    typedef std::multiset<ValueTp> Set;
+    testSet<Set, ValueTp, ValueTp const*>();
+  }
+  {
+    typedef int ValueTp;
+    typedef test_allocator<ValueTp> Alloc;
+    typedef std::multiset<ValueTp, std::less<ValueTp>, Alloc> Set;
+    testSet<Set, ValueTp, ValueTp const*>();
+  }
+#if TEST_STD_VER >= 11
+  {
+    typedef int ValueTp;
+    typedef min_allocator<ValueTp> Alloc;
+    typedef std::multiset<ValueTp, std::less<ValueTp>, Alloc> Set;
+    testSet<Set, ValueTp, min_pointer<const ValueTp>>();
+  }
+#endif
+}

Added: libcxx/trunk/test/std/containers/associative/map/incomplete_type.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/containers/associative/map/incomplete_type.pass.cpp?rev=261416&view=auto
==============================================================================
--- libcxx/trunk/test/std/containers/associative/map/incomplete_type.pass.cpp (added)
+++ libcxx/trunk/test/std/containers/associative/map/incomplete_type.pass.cpp Fri Feb 19 23:28:30 2016
@@ -0,0 +1,29 @@
+//===----------------------------------------------------------------------===//
+//
+//                     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>
+
+// Check that std::map and it's iterators can be instantiated with an incomplete
+// type.
+
+#include <map>
+
+struct A {
+    typedef std::map<A, A> Map;
+    int data;
+    Map m;
+    Map::iterator it;
+    Map::const_iterator cit;
+};
+
+inline bool operator==(A const& L, A const& R) { return &L == &R; }
+inline bool operator<(A const& L, A const& R)  { return L.data < R.data; }
+int main() {
+    A a;
+}

Added: libcxx/trunk/test/std/containers/associative/multimap/incomplete_type.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/containers/associative/multimap/incomplete_type.pass.cpp?rev=261416&view=auto
==============================================================================
--- libcxx/trunk/test/std/containers/associative/multimap/incomplete_type.pass.cpp (added)
+++ libcxx/trunk/test/std/containers/associative/multimap/incomplete_type.pass.cpp Fri Feb 19 23:28:30 2016
@@ -0,0 +1,29 @@
+//===----------------------------------------------------------------------===//
+//
+//                     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>
+
+// Check that std::multimap and it's iterators can be instantiated with an incomplete
+// type.
+
+#include <map>
+
+struct A {
+    typedef std::multimap<A, A> Map;
+    int data;
+    Map m;
+    Map::iterator it;
+    Map::const_iterator cit;
+};
+
+inline bool operator==(A const& L, A const& R) { return &L == &R; }
+inline bool operator<(A const& L, A const& R)  { return L.data < R.data; }
+int main() {
+    A a;
+}

Added: libcxx/trunk/test/std/containers/associative/multiset/incomplete_type.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/containers/associative/multiset/incomplete_type.pass.cpp?rev=261416&view=auto
==============================================================================
--- libcxx/trunk/test/std/containers/associative/multiset/incomplete_type.pass.cpp (added)
+++ libcxx/trunk/test/std/containers/associative/multiset/incomplete_type.pass.cpp Fri Feb 19 23:28:30 2016
@@ -0,0 +1,29 @@
+//===----------------------------------------------------------------------===//
+//
+//                     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>
+
+// Check that std::multiset and it's iterators can be instantiated with an incomplete
+// type.
+
+#include <set>
+
+struct A {
+    typedef std::multiset<A> Set;
+    int data;
+    Set m;
+    Set::iterator it;
+    Set::const_iterator cit;
+};
+
+inline bool operator==(A const& L, A const& R) { return &L == &R; }
+inline bool operator<(A const& L, A const& R)  { return L.data < R.data; }
+int main() {
+    A a;
+}

Added: libcxx/trunk/test/std/containers/associative/set/incomplete_type.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/containers/associative/set/incomplete_type.pass.cpp?rev=261416&view=auto
==============================================================================
--- libcxx/trunk/test/std/containers/associative/set/incomplete_type.pass.cpp (added)
+++ libcxx/trunk/test/std/containers/associative/set/incomplete_type.pass.cpp Fri Feb 19 23:28:30 2016
@@ -0,0 +1,29 @@
+//===----------------------------------------------------------------------===//
+//
+//                     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>
+
+// Check that std::set and it's iterators can be instantiated with an incomplete
+// type.
+
+#include <set>
+
+struct A {
+    typedef std::set<A> Set;
+    int data;
+    Set m;
+    Set::iterator it;
+    Set::const_iterator cit;
+};
+
+inline bool operator==(A const& L, A const& R) { return &L == &R; }
+inline bool operator<(A const& L, A const& R)  { return L.data < R.data; }
+int main() {
+    A a;
+}




More information about the cfe-commits mailing list