From 089a7cc5dea665f4088ed6b587e2f6ea058d7581 Mon Sep 17 00:00:00 2001 From: Eric Fiselier Date: Sat, 20 Feb 2016 05:28:30 +0000 Subject: [PATCH] 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. 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. llvm-svn: 261416 --- libcxx/include/__tree | 229 +++++++++++++----- libcxx/include/map | 32 +-- .../tree_key_value_traits.pass.cpp | 59 +++++ .../associative/iterator_types.pass.cpp | 131 ++++++++++ .../associative/map/incomplete_type.pass.cpp | 29 +++ .../multimap/incomplete_type.pass.cpp | 29 +++ .../multiset/incomplete_type.pass.cpp | 29 +++ .../associative/set/incomplete_type.pass.cpp | 29 +++ 8 files changed, 489 insertions(+), 78 deletions(-) create mode 100644 libcxx/test/libcxx/containers/associative/tree_key_value_traits.pass.cpp create mode 100644 libcxx/test/std/containers/associative/iterator_types.pass.cpp create mode 100644 libcxx/test/std/containers/associative/map/incomplete_type.pass.cpp create mode 100644 libcxx/test/std/containers/associative/multimap/incomplete_type.pass.cpp create mode 100644 libcxx/test/std/containers/associative/multiset/incomplete_type.pass.cpp create mode 100644 libcxx/test/std/containers/associative/set/incomplete_type.pass.cpp diff --git a/libcxx/include/__tree b/libcxx/include/__tree index 94565bc3f74c..1536b5d6d2c9 100644 --- a/libcxx/include/__tree +++ b/libcxx/include/__tree @@ -29,6 +29,22 @@ template template class _LIBCPP_TYPE_VIS_ONLY __tree_const_iterator; +template class __tree_end_node; +template class __tree_node_base; +template class __tree_node; + +#ifndef _LIBCPP_CXX03_LANG +template +union __value_type; +#else +template +struct __value_type; +#endif + +template class __map_node_destructor; +template class _LIBCPP_TYPE_VIS_ONLY __map_iterator; +template class _LIBCPP_TYPE_VIS_ONLY __map_const_iterator; + /* _NodePtr algorithms @@ -494,14 +510,12 @@ __tree_remove(_NodePtr __root, _NodePtr __z) _NOEXCEPT } } -template class __map_node_destructor; - template class __tree_node_destructor { typedef _Allocator allocator_type; typedef allocator_traits __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 friend class __map_node_destructor; }; +// node traits + +template +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 +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 __container_value_type; + typedef pair<_Key, _Tp> __nc_value_type; + typedef __container_value_type __map_value_type; + static const bool __is_map = true; +}; + +template +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::element_type, void>::value), + "_VoidPtr does not point to unqualified void type"); +}; + +template , + bool = _KVTypes::__is_map> +struct __tree_map_pointer_types {}; + +template +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 ::element_type> +struct __tree_node_types; + +template +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::type, + _NodePtr>::value), "_VoidPtr does not rebind to _NodePtr."); +}; + +template +struct __make_tree_node_types { + typedef typename __rebind_pointer<_VoidPtr, __tree_node<_ValueTp, _VoidPtr> >::type + _NodePtr; + typedef __tree_node_types<_NodePtr> type; +}; + // node template @@ -546,18 +646,14 @@ public: template 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 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 @@ -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 _LIBCPP_TYPE_VIS_ONLY __map_iterator; -template class _LIBCPP_TYPE_VIS_ONLY __map_const_iterator; - template 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(__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(__ptr_))); + __tree_prev(static_cast<__node_base_pointer>(__ptr_))); return *this; } _LIBCPP_INLINE_VISIBILITY @@ -658,21 +751,22 @@ private: template friend class _LIBCPP_TYPE_VIS_ONLY multiset; }; -template +template 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 - __non_const_iterator; + typedef __tree_iterator + __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 __alloc_traits; + typedef typename __make_tree_node_types::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 __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; -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; + typedef allocator_traits<__node_allocator> __node_traits; +private: + // 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 __pair3_; diff --git a/libcxx/include/map b/libcxx/include/map index 87add437a545..b58846b044a6 100644 --- a/libcxx/include/map +++ b/libcxx/include/map @@ -564,13 +564,11 @@ class __map_node_destructor { typedef _Allocator allocator_type; typedef allocator_traits __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 multimap; template class __map_const_iterator; -#if __cplusplus >= 201103L +#ifndef _LIBCPP_CXX03_LANG template union __value_type @@ -697,19 +695,17 @@ struct __extract_key_value_types<__value_type<_Key, _Tp> > template 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::type - pointer; + typedef typename _NodeTypes::__map_value_type_pointer pointer; _LIBCPP_INLINE_VISIBILITY __map_iterator() _NOEXCEPT {} @@ -758,19 +754,17 @@ public: template 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::type - pointer; + typedef typename _NodeTypes::__const_map_value_type_pointer pointer; _LIBCPP_INLINE_VISIBILITY __map_const_iterator() _NOEXCEPT {} diff --git a/libcxx/test/libcxx/containers/associative/tree_key_value_traits.pass.cpp b/libcxx/test/libcxx/containers/associative/tree_key_value_traits.pass.cpp new file mode 100644 index 000000000000..0befd749a50c --- /dev/null +++ b/libcxx/test/libcxx/containers/associative/tree_key_value_traits.pass.cpp @@ -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 +#include +#include + +#include "test_macros.h" +#include "min_allocator.h" + +void testKeyValueTrait() { + { + typedef int Tp; + typedef std::__tree_key_value_types Traits; + static_assert((std::is_same::value), ""); + static_assert((std::is_same::value), ""); + static_assert((std::is_same::value), ""); + static_assert(Traits::__is_map == false, ""); + } + { + typedef std::pair Tp; + typedef std::__tree_key_value_types Traits; + static_assert((std::is_same::value), ""); + static_assert((std::is_same::value), ""); + static_assert((std::is_same::value), ""); + static_assert(Traits::__is_map == false, ""); + } + { + typedef std::pair Tp; + typedef std::__tree_key_value_types Traits; + static_assert((std::is_same::value), ""); + static_assert((std::is_same::value), ""); + static_assert((std::is_same::value), ""); + static_assert(Traits::__is_map == false, ""); + } + { + typedef std::__value_type Tp; + typedef std::__tree_key_value_types Traits; + static_assert((std::is_same::value), ""); + static_assert((std::is_same::value), ""); + static_assert((std::is_same::value), ""); + static_assert((std::is_same >::value), ""); + static_assert((std::is_same >::value), ""); + static_assert(Traits::__is_map == true, ""); + } +} + +int main() { + testKeyValueTrait(); +} diff --git a/libcxx/test/std/containers/associative/iterator_types.pass.cpp b/libcxx/test/std/containers/associative/iterator_types.pass.cpp new file mode 100644 index 000000000000..2026219d86cb --- /dev/null +++ b/libcxx/test/std/containers/associative/iterator_types.pass.cpp @@ -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 +#include +#include + +#include "test_macros.h" +#include "min_allocator.h" +#include "test_allocator.h" + + +template +void testMap() { + typedef typename Map::difference_type Diff; + { + typedef typename Map::iterator It; + static_assert((std::is_same::value), ""); + static_assert((std::is_same::value), ""); + static_assert((std::is_same::value), ""); + static_assert((std::is_same::value), ""); + } + { + typedef typename Map::const_iterator It; + static_assert((std::is_same::value), ""); + static_assert((std::is_same::value), ""); + static_assert((std::is_same::value), ""); + static_assert((std::is_same::value), ""); + } +} + + +template +void testSet() { + static_assert((std::is_same::value), ""); + typedef typename Set::difference_type Diff; + { + typedef typename Set::iterator It; + static_assert((std::is_same::value), ""); + static_assert((std::is_same::value), ""); + static_assert((std::is_same::value), ""); + static_assert((std::is_same::value), ""); + + } +} + +int main() { + { + typedef std::map Map; + typedef std::pair ValueTp; + testMap(); + } + { + typedef std::pair ValueTp; + typedef test_allocator Alloc; + typedef std::map, Alloc> Map; + testMap(); + } +#if TEST_STD_VER >= 11 + { + typedef std::pair ValueTp; + typedef min_allocator Alloc; + typedef std::map, Alloc> Map; + testMap, min_pointer>(); + } +#endif + { + typedef std::multimap Map; + typedef std::pair ValueTp; + testMap(); + } + { + typedef std::pair ValueTp; + typedef test_allocator Alloc; + typedef std::multimap, Alloc> Map; + testMap(); + } +#if TEST_STD_VER >= 11 + { + typedef std::pair ValueTp; + typedef min_allocator Alloc; + typedef std::multimap, Alloc> Map; + testMap, min_pointer>(); + } +#endif + { + typedef int ValueTp; + typedef std::set Set; + testSet(); + } + { + typedef int ValueTp; + typedef test_allocator Alloc; + typedef std::set, Alloc> Set; + testSet(); + } +#if TEST_STD_VER >= 11 + { + typedef int ValueTp; + typedef min_allocator Alloc; + typedef std::set, Alloc> Set; + testSet>(); + } +#endif + { + typedef int ValueTp; + typedef std::multiset Set; + testSet(); + } + { + typedef int ValueTp; + typedef test_allocator Alloc; + typedef std::multiset, Alloc> Set; + testSet(); + } +#if TEST_STD_VER >= 11 + { + typedef int ValueTp; + typedef min_allocator Alloc; + typedef std::multiset, Alloc> Set; + testSet>(); + } +#endif +} diff --git a/libcxx/test/std/containers/associative/map/incomplete_type.pass.cpp b/libcxx/test/std/containers/associative/map/incomplete_type.pass.cpp new file mode 100644 index 000000000000..84c2451ce087 --- /dev/null +++ b/libcxx/test/std/containers/associative/map/incomplete_type.pass.cpp @@ -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. +// +//===----------------------------------------------------------------------===// + +// + +// Check that std::map and it's iterators can be instantiated with an incomplete +// type. + +#include + +struct A { + typedef std::map 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; +} diff --git a/libcxx/test/std/containers/associative/multimap/incomplete_type.pass.cpp b/libcxx/test/std/containers/associative/multimap/incomplete_type.pass.cpp new file mode 100644 index 000000000000..c461eb38139d --- /dev/null +++ b/libcxx/test/std/containers/associative/multimap/incomplete_type.pass.cpp @@ -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. +// +//===----------------------------------------------------------------------===// + +// + +// Check that std::multimap and it's iterators can be instantiated with an incomplete +// type. + +#include + +struct A { + typedef std::multimap 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; +} diff --git a/libcxx/test/std/containers/associative/multiset/incomplete_type.pass.cpp b/libcxx/test/std/containers/associative/multiset/incomplete_type.pass.cpp new file mode 100644 index 000000000000..0355e18f9f29 --- /dev/null +++ b/libcxx/test/std/containers/associative/multiset/incomplete_type.pass.cpp @@ -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. +// +//===----------------------------------------------------------------------===// + +// + +// Check that std::multiset and it's iterators can be instantiated with an incomplete +// type. + +#include + +struct A { + typedef std::multiset 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; +} diff --git a/libcxx/test/std/containers/associative/set/incomplete_type.pass.cpp b/libcxx/test/std/containers/associative/set/incomplete_type.pass.cpp new file mode 100644 index 000000000000..d3a1d6638d7e --- /dev/null +++ b/libcxx/test/std/containers/associative/set/incomplete_type.pass.cpp @@ -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. +// +//===----------------------------------------------------------------------===// + +// + +// Check that std::set and it's iterators can be instantiated with an incomplete +// type. + +#include + +struct A { + typedef std::set 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; +}