From a6ac16d0c44825fb101f610eb9a9b5321bad4d28 Mon Sep 17 00:00:00 2001 From: "luz.paz" Date: Sun, 23 Sep 2018 15:54:39 -0400 Subject: [PATCH 01/12] container: misc-typos Found via `codespell -q 3 -L iff,nd` --- doc/container.qbk | 4 ++-- example/doc_emplace.cpp | 2 +- include/boost/container/allocator_traits.hpp | 2 +- include/boost/container/stable_vector.hpp | 2 +- include/boost/container/static_vector.hpp | 2 +- include/boost/container/string.hpp | 2 +- include/boost/container/vector.hpp | 2 +- src/dlmalloc_2_8_6.c | 8 ++++---- src/dlmalloc_ext_2_8_6.c | 2 +- test/monotonic_buffer_resource_test.cpp | 4 ++-- 10 files changed, 15 insertions(+), 15 deletions(-) diff --git a/doc/container.qbk b/doc/container.qbk index 66ba429..1ecccaa 100644 --- a/doc/container.qbk +++ b/doc/container.qbk @@ -365,8 +365,8 @@ operations provide stronger exception safety guarantees than in vector: [[erase] [no-throw unless copy/move construction/assignment of `T` throw (basic)] [no-throw]] ] -[*Memory overhead]. The C++ standard does not specifiy requirements on memory consumption, but virtually any implementation -of `vector` has the same behavior wih respect to memory usage: the memory allocated by a `vector` v with n elements of type T +[*Memory overhead]. The C++ standard does not specify requirements on memory consumption, but virtually any implementation +of `vector` has the same behavior with respect to memory usage: the memory allocated by a `vector` v with n elements of type T is m[sub v] = c\u2219e, diff --git a/example/doc_emplace.cpp b/example/doc_emplace.cpp index 2fe4aa0..10ab743 100644 --- a/example/doc_emplace.cpp +++ b/example/doc_emplace.cpp @@ -31,7 +31,7 @@ int main () list l; non_copy_movable ncm; - //A new element will be built calling non_copy_movable(int) contructor + //A new element will be built calling non_copy_movable(int) constructor l.emplace(l.begin(), 0); assert(l.size() == 1); diff --git a/include/boost/container/allocator_traits.hpp b/include/boost/container/allocator_traits.hpp index af32f18..4e1a1da 100644 --- a/include/boost/container/allocator_traits.hpp +++ b/include/boost/container/allocator_traits.hpp @@ -151,7 +151,7 @@ struct allocator_traits //! Allocator::void_pointer if such a type exists ; otherwise, pointer_traits::rebind. //! typedef see_documentation void_pointer; - //! Allocator::const_void_pointer if such a type exists ; otherwis e, pointer_traits::rebind::rebind::difference_type. diff --git a/include/boost/container/stable_vector.hpp b/include/boost/container/stable_vector.hpp index 41f45df..a2a4921 100644 --- a/include/boost/container/stable_vector.hpp +++ b/include/boost/container/stable_vector.hpp @@ -793,7 +793,7 @@ class stable_vector BOOST_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value || allocator_traits_type::is_always_equal::value) { - //for move constructor, no aliasing (&x != this) is assummed. + //for move constructor, no aliasing (&x != this) is assumed. BOOST_ASSERT(this != &x); node_allocator_type &this_alloc = this->priv_node_alloc(); node_allocator_type &x_alloc = x.priv_node_alloc(); diff --git a/include/boost/container/static_vector.hpp b/include/boost/container/static_vector.hpp index b40d5c3..f230763 100644 --- a/include/boost/container/static_vector.hpp +++ b/include/boost/container/static_vector.hpp @@ -96,7 +96,7 @@ class static_storage_allocator //! Insertion beyond the capacity result in throwing std::bad_alloc() if exceptions are enabled or //! calling throw_bad_alloc() if not enabled. //! -//! std::out_of_range is thrown if out of bound access is performed in at() if exceptions are +//! std::out_of_range is thrown if out of bounds access is performed in at() if exceptions are //! enabled, throw_out_of_range() if not enabled. //! //!@tparam Value The type of element that will be stored. diff --git a/include/boost/container/string.hpp b/include/boost/container/string.hpp index e14e10f..99120a1 100644 --- a/include/boost/container/string.hpp +++ b/include/boost/container/string.hpp @@ -896,7 +896,7 @@ class basic_string BOOST_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value || allocator_traits_type::is_always_equal::value) { - //for move constructor, no aliasing (&x != this) is assummed. + //for move constructor, no aliasing (&x != this) is assumed. BOOST_ASSERT(this != &x); allocator_type &this_alloc = this->alloc(); allocator_type &x_alloc = x.alloc(); diff --git a/include/boost/container/vector.hpp b/include/boost/container/vector.hpp index 46d9e7a..f3372e2 100644 --- a/include/boost/container/vector.hpp +++ b/include/boost/container/vector.hpp @@ -2396,7 +2396,7 @@ class vector , dtl::is_different >::type * = 0) { - //for move assignment, no aliasing (&x != this) is assummed. + //for move assignment, no aliasing (&x != this) is assumed. BOOST_ASSERT(this != &x); allocator_type &this_alloc = this->m_holder.alloc(); allocator_type &x_alloc = x.m_holder.alloc(); diff --git a/src/dlmalloc_2_8_6.c b/src/dlmalloc_2_8_6.c index 649cfbc..7a53d35 100644 --- a/src/dlmalloc_2_8_6.c +++ b/src/dlmalloc_2_8_6.c @@ -1762,7 +1762,7 @@ static FORCEINLINE int win32munmap(void* ptr, size_t size) { #define CALL_MREMAP(addr, osz, nsz, mv) MFAIL #endif /* HAVE_MMAP && HAVE_MREMAP */ -/* mstate bit set if continguous morecore disabled or failed */ +/* mstate bit set if contiguous morecore disabled or failed */ #define USE_NONCONTIGUOUS_BIT (4U) /* segment bit set in create_mspace_with_base */ @@ -4676,7 +4676,7 @@ void* dlmalloc(size_t bytes) { void dlfree(void* mem) { /* - Consolidate freed chunks with preceeding or succeeding bordering + Consolidate freed chunks with preceding or succeeding bordering free chunks, if they exist, and then place in a bin. Intermixed with special cases for top, dv, mmapped chunks, and usage errors. */ @@ -6210,10 +6210,10 @@ History: Wolfram Gloger (Gloger@lrz.uni-muenchen.de). * Use last_remainder in more cases. * Pack bins using idea from colin@nyx10.cs.du.edu - * Use ordered bins instead of best-fit threshhold + * Use ordered bins instead of best-fit threshold * Eliminate block-local decls to simplify tracing and debugging. * Support another case of realloc via move into top - * Fix error occuring when initial sbrk_base not word-aligned. + * Fix error occurring when initial sbrk_base not word-aligned. * Rely on page size for units instead of SBRK_UNIT to avoid surprises about sbrk alignment conventions. * Add mallinfo, mallopt. Thanks to Raymond Nijssen diff --git a/src/dlmalloc_ext_2_8_6.c b/src/dlmalloc_ext_2_8_6.c index 3328d72..b0fc507 100644 --- a/src/dlmalloc_ext_2_8_6.c +++ b/src/dlmalloc_ext_2_8_6.c @@ -881,7 +881,7 @@ static int internal_node_multialloc /*Error if wrong element_size parameter */ if( !element_size || - /*OR Error if n_elements less thatn contiguous_elements */ + /*OR Error if n_elements less than contiguous_elements */ ((contiguous_elements + 1) > (DL_MULTIALLOC_DEFAULT_CONTIGUOUS + 1) && n_elements < contiguous_elements) || /* OR Error if integer overflow */ (SQRT_MAX_SIZE_T < (element_req_size | contiguous_elements) && diff --git a/test/monotonic_buffer_resource_test.cpp b/test/monotonic_buffer_resource_test.cpp index 2f3f0b1..4923e24 100644 --- a/test/monotonic_buffer_resource_test.cpp +++ b/test/monotonic_buffer_resource_test.cpp @@ -352,7 +352,7 @@ void test_do_allocate() BOOST_TEST(dmbr.remaining_storage(1u) == sizeof(buf)); //Allocate all remaining storage dmbr.do_allocate(dmbr.remaining_storage(1u), 1u); - //No new allocation should have ocurred + //No new allocation should have occurred BOOST_TEST(mrl.m_info.size() == 0u); BOOST_TEST(dmbr.remaining_storage(1u) == 0u); } @@ -433,7 +433,7 @@ void test_release() //Allocate all remaining storage mr.allocate(monr.remaining_storage(1u), 1u); BOOST_TEST(monr.current_buffer() == ((char*)&buf + sizeof(buf))); - //No new allocation should have ocurred + //No new allocation should have occurred BOOST_TEST(monr.remaining_storage(1u) == 0u); //Release and check memory was released and the original buffer is back monr.release(); From b7355bb2b4a206d5dc96469151907c82ec120c13 Mon Sep 17 00:00:00 2001 From: Tobias Ludwig Date: Mon, 29 Oct 2018 22:31:52 +0100 Subject: [PATCH 02/12] add missing warning re-enabling include fixes msvc warning C5032: "detected #pragma warning(push) with no corresponding #pragma warning(pop)" --- include/boost/container/detail/thread_mutex.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/boost/container/detail/thread_mutex.hpp b/include/boost/container/detail/thread_mutex.hpp index 628f28b..66d64b9 100644 --- a/include/boost/container/detail/thread_mutex.hpp +++ b/include/boost/container/detail/thread_mutex.hpp @@ -176,4 +176,6 @@ class thread_mutex #endif //BOOST_HAS_PTHREADS +#include + #endif // #ifndef BOOST_CONTAINER_DETAIL_THREAD_MUTEX_HPP From 3afe49245fc18b54f3967b06a61a62e9d75d12f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Sat, 10 Nov 2018 10:46:56 +0100 Subject: [PATCH 03/12] Updated changelog with deprectation and Pull #86 --- doc/container.qbk | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/doc/container.qbk b/doc/container.qbk index 66ba429..14070de 100644 --- a/doc/container.qbk +++ b/doc/container.qbk @@ -77,7 +77,8 @@ instructions, that's already been done for you. * Visual C++ >= 7.1. * GCC >= 4.1. -* Intel C++ >= 9.0 + +[warning GCC < 4.3 and MSVC < 9.0 are deprecated and will be removed in the next version.] [endsect] @@ -1242,6 +1243,8 @@ use [*Boost.Container]? There are several reasons for that: [section:release_notes_boost_1_69_00 Boost 1.69 Release] +* Deprecated GCC < 4.3 and MSVC < 9.0 (Visual 2008) compilers. + * Implemented C++20 `contains()` for associative containers as specified in [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0458r2.html P0458R2: Checking for Existence of an Element in Associative Containers]. @@ -1250,6 +1253,7 @@ use [*Boost.Container]? There are several reasons for that: * Fixed bugs: * [@https://github.com/boostorg/container/issues/82 GitHub #82: ['"Function definition in header file"]]. + * [@https://github.com/boostorg/container/pull/86 GitHub #86: ['"Add missing warning re-enabling include"]]. [endsect] From 10a618afe88ed16a9662316d2f5ff51d6041f4c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Sat, 10 Nov 2018 23:12:46 +0100 Subject: [PATCH 04/12] Fix GitHub #83: ("Iterator zero incrementing leads to assert on empty vector") --- doc/container.qbk | 1 + include/boost/container/vector.hpp | 10 +++++----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/doc/container.qbk b/doc/container.qbk index 14070de..84c9f3f 100644 --- a/doc/container.qbk +++ b/doc/container.qbk @@ -1253,6 +1253,7 @@ use [*Boost.Container]? There are several reasons for that: * Fixed bugs: * [@https://github.com/boostorg/container/issues/82 GitHub #82: ['"Function definition in header file"]]. + * [@https://github.com/boostorg/container/issues/83 GitHub #83: ['"Iterator zero incrementing leads to assert on empty vector"]]. * [@https://github.com/boostorg/container/pull/86 GitHub #86: ['"Add missing warning re-enabling include"]]. [endsect] diff --git a/include/boost/container/vector.hpp b/include/boost/container/vector.hpp index 8b863ab..19cbaed 100644 --- a/include/boost/container/vector.hpp +++ b/include/boost/container/vector.hpp @@ -145,19 +145,19 @@ class vec_iterator //Arithmetic BOOST_CONTAINER_FORCEINLINE vec_iterator& operator+=(difference_type off) BOOST_NOEXCEPT_OR_NOTHROW - { BOOST_ASSERT(!!m_ptr); m_ptr += off; return *this; } + { BOOST_ASSERT(m_ptr || !off); m_ptr += off; return *this; } BOOST_CONTAINER_FORCEINLINE vec_iterator& operator-=(difference_type off) BOOST_NOEXCEPT_OR_NOTHROW - { BOOST_ASSERT(!!m_ptr); m_ptr -= off; return *this; } + { BOOST_ASSERT(m_ptr || !off); m_ptr -= off; return *this; } BOOST_CONTAINER_FORCEINLINE friend vec_iterator operator+(const vec_iterator &x, difference_type off) BOOST_NOEXCEPT_OR_NOTHROW - { BOOST_ASSERT(!!x.m_ptr); return vec_iterator(x.m_ptr+off); } + { BOOST_ASSERT(x.m_ptr || !off); return vec_iterator(x.m_ptr+off); } BOOST_CONTAINER_FORCEINLINE friend vec_iterator operator+(difference_type off, vec_iterator right) BOOST_NOEXCEPT_OR_NOTHROW - { BOOST_ASSERT(!!right.m_ptr); right.m_ptr += off; return right; } + { BOOST_ASSERT(right.m_ptr || !off); right.m_ptr += off; return right; } BOOST_CONTAINER_FORCEINLINE friend vec_iterator operator-(vec_iterator left, difference_type off) BOOST_NOEXCEPT_OR_NOTHROW - { BOOST_ASSERT(!!left.m_ptr); left.m_ptr -= off; return left; } + { BOOST_ASSERT(left.m_ptr || !off); left.m_ptr -= off; return left; } BOOST_CONTAINER_FORCEINLINE friend difference_type operator-(const vec_iterator &left, const vec_iterator& right) BOOST_NOEXCEPT_OR_NOTHROW { return left.m_ptr - right.m_ptr; } From 059133a3453378147f2bee2d9968544f64213936 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Sun, 11 Nov 2018 00:20:22 +0100 Subject: [PATCH 05/12] Fix GitHub #79 ("Mark small_vector move operations noexcept") --- doc/container.qbk | 1 + include/boost/container/small_vector.hpp | 4 ++++ include/boost/container/static_vector.hpp | 1 + 3 files changed, 6 insertions(+) diff --git a/doc/container.qbk b/doc/container.qbk index a87742d..9528e83 100644 --- a/doc/container.qbk +++ b/doc/container.qbk @@ -1252,6 +1252,7 @@ use [*Boost.Container]? There are several reasons for that: * Fixed serious bug in heterogeneous lookup functions (is_transparent was broken). * Fixed bugs: + * [@https://github.com/boostorg/container/issues/79 GitHub #79: ['"Mark small_vector move operations noexcept"]]. * [@https://github.com/boostorg/container/issues/82 GitHub #82: ['"Function definition in header file"]]. * [@https://github.com/boostorg/container/issues/83 GitHub #83: ['"Iterator zero incrementing leads to assert on empty vector"]]. * [@https://github.com/boostorg/container/pull/85 GitHub #85: ['"container: misc-typos"]]. diff --git a/include/boost/container/small_vector.hpp b/include/boost/container/small_vector.hpp index 6f5c050..c0edac8 100644 --- a/include/boost/container/small_vector.hpp +++ b/include/boost/container/small_vector.hpp @@ -608,6 +608,7 @@ class small_vector : public small_vector_base { this->move_construct_impl(other, other.get_stored_allocator()); } BOOST_CONTAINER_FORCEINLINE small_vector(BOOST_RV_REF(small_vector) other) + BOOST_NOEXCEPT_IF(boost::container::dtl::is_nothrow_move_assignable::value) : base_type(initial_capacity_t(), internal_capacity(), ::boost::move(other.get_stored_allocator())) { this->move_construct_impl(other, other.get_stored_allocator()); } @@ -627,6 +628,9 @@ class small_vector : public small_vector_base { return static_cast(this->base_type::operator=(static_cast(other))); } BOOST_CONTAINER_FORCEINLINE small_vector& operator=(BOOST_RV_REF(small_vector) other) + BOOST_NOEXCEPT_IF(boost::container::dtl::is_nothrow_move_assignable::value + && (allocator_traits_type::propagate_on_container_move_assignment::value + || allocator_traits_type::is_always_equal::value)) { return static_cast(this->base_type::operator=(BOOST_MOVE_BASE(base_type, other))); } BOOST_CONTAINER_FORCEINLINE small_vector& operator=(const base_type &other) diff --git a/include/boost/container/static_vector.hpp b/include/boost/container/static_vector.hpp index f230763..059640e 100644 --- a/include/boost/container/static_vector.hpp +++ b/include/boost/container/static_vector.hpp @@ -372,6 +372,7 @@ public: //! @par Complexity //! Linear O(N). BOOST_CONTAINER_FORCEINLINE static_vector & operator=(BOOST_RV_REF(static_vector) other) + BOOST_NOEXCEPT_IF(boost::container::dtl::is_nothrow_move_assignable::value) { return static_cast(base_t::operator=(BOOST_MOVE_BASE(base_t, other))); } From 2bc6f4d1a030661b3242244cd5f90260f4293620 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Sun, 11 Nov 2018 01:10:01 +0100 Subject: [PATCH 06/12] Fixes GitHub #84 ("Allow vector to be assigned to itself"). --- doc/container.qbk | 1 + include/boost/container/vector.hpp | 16 +++++++++++----- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/doc/container.qbk b/doc/container.qbk index 9528e83..5060c4c 100644 --- a/doc/container.qbk +++ b/doc/container.qbk @@ -1255,6 +1255,7 @@ use [*Boost.Container]? There are several reasons for that: * [@https://github.com/boostorg/container/issues/79 GitHub #79: ['"Mark small_vector move operations noexcept"]]. * [@https://github.com/boostorg/container/issues/82 GitHub #82: ['"Function definition in header file"]]. * [@https://github.com/boostorg/container/issues/83 GitHub #83: ['"Iterator zero incrementing leads to assert on empty vector"]]. + * [@https://github.com/boostorg/container/pull/84 GitHub #84: ['"Allow vector to be assigned to itself"]]. * [@https://github.com/boostorg/container/pull/85 GitHub #85: ['"container: misc-typos"]]. * [@https://github.com/boostorg/container/pull/86 GitHub #86: ['"Add missing warning re-enabling include"]]. diff --git a/include/boost/container/vector.hpp b/include/boost/container/vector.hpp index f8736d8..aa4b505 100644 --- a/include/boost/container/vector.hpp +++ b/include/boost/container/vector.hpp @@ -1131,7 +1131,6 @@ class vector BOOST_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value || allocator_traits_type::is_always_equal::value) { - BOOST_ASSERT(&x != this); this->priv_move_assign(boost::move(x)); return *this; } @@ -2407,7 +2406,8 @@ class vector >::type * = 0) { //for move assignment, no aliasing (&x != this) is assumed. - BOOST_ASSERT(this != &x); + //x.size() == 0 is allowed for buggy std libraries. + BOOST_ASSERT(this != &x || x.size() == 0); allocator_type &this_alloc = this->m_holder.alloc(); allocator_type &x_alloc = x.m_holder.alloc(); const bool propagate_alloc = allocator_traits_type::propagate_on_container_move_assignment::value; @@ -2425,7 +2425,8 @@ class vector } else if(is_propagable_from_x){ this->clear(); - this->m_holder.deallocate(this->m_holder.m_start, this->m_holder.m_capacity); + if(BOOST_LIKELY(!!this->m_holder.m_start)) + this->m_holder.deallocate(this->m_holder.m_start, this->m_holder.m_capacity); this->m_holder.steal_resources(x.m_holder); } //Else do a one by one move @@ -2489,6 +2490,9 @@ class vector this->m_holder.swap_resources(x.m_holder); } else{ + if (BOOST_UNLIKELY(&x == this)) + return; + //Else swap element by element... bool const t_smaller = this->size() < x.size(); vector &sml = t_smaller ? *this : x; @@ -2664,7 +2668,8 @@ class vector if(cp){ const size_type sz = this->size(); if(!sz){ - this->m_holder.deallocate(this->m_holder.m_start, cp); + if(BOOST_LIKELY(!!this->m_holder.m_start)) + this->m_holder.deallocate(this->m_holder.m_start, cp); this->m_holder.m_start = pointer(); this->m_holder.m_capacity = 0; } @@ -2690,7 +2695,8 @@ class vector if(cp){ const size_type sz = this->size(); if(!sz){ - this->m_holder.deallocate(this->m_holder.m_start, cp); + if(BOOST_LIKELY(!!this->m_holder.m_start)) + this->m_holder.deallocate(this->m_holder.m_start, cp); this->m_holder.m_start = pointer(); this->m_holder.m_capacity = 0; } From e94c779b568e0866abe1411d0fcdff0039dde617 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Sun, 11 Nov 2018 01:38:27 +0100 Subject: [PATCH 07/12] Fix GitHub #77 ("warning: 'sbrk' is deprecated") --- doc/container.qbk | 1 + src/dlmalloc_ext_2_8_6.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/doc/container.qbk b/doc/container.qbk index 5060c4c..9e66954 100644 --- a/doc/container.qbk +++ b/doc/container.qbk @@ -1252,6 +1252,7 @@ use [*Boost.Container]? There are several reasons for that: * Fixed serious bug in heterogeneous lookup functions (is_transparent was broken). * Fixed bugs: + * [@https://github.com/boostorg/container/issues/77 GitHub #77: ['"warning: 'sbrk' is deprecated"]]. * [@https://github.com/boostorg/container/issues/79 GitHub #79: ['"Mark small_vector move operations noexcept"]]. * [@https://github.com/boostorg/container/issues/82 GitHub #82: ['"Function definition in header file"]]. * [@https://github.com/boostorg/container/issues/83 GitHub #83: ['"Iterator zero incrementing leads to assert on empty vector"]]. diff --git a/src/dlmalloc_ext_2_8_6.c b/src/dlmalloc_ext_2_8_6.c index d0e01f8..918ce02 100644 --- a/src/dlmalloc_ext_2_8_6.c +++ b/src/dlmalloc_ext_2_8_6.c @@ -19,6 +19,8 @@ #define MSPACES 1 #define NO_MALLINFO 1 #define NO_MALLOC_STATS 1 +//disable sbrk as it's deprecated in some systems and weakens ASLR +#define HAVE_MORECORE 0 #if !defined(NDEBUG) From 9bba03450f682cfca467631dc7f7bf982be97b40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Sun, 11 Nov 2018 02:03:30 +0100 Subject: [PATCH 08/12] Update changelog and test function for GitHub #81 ("Vector with custom allocator does not support value types with operator&") --- doc/container.qbk | 1 + test/vector_test.cpp | 26 ++++++++++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/doc/container.qbk b/doc/container.qbk index 9e66954..70b4273 100644 --- a/doc/container.qbk +++ b/doc/container.qbk @@ -1254,6 +1254,7 @@ use [*Boost.Container]? There are several reasons for that: * Fixed bugs: * [@https://github.com/boostorg/container/issues/77 GitHub #77: ['"warning: 'sbrk' is deprecated"]]. * [@https://github.com/boostorg/container/issues/79 GitHub #79: ['"Mark small_vector move operations noexcept"]]. + * [@https://github.com/boostorg/container/issues/81 GitHub #81: ['"Vector with custom allocator does not support value types with operator&"]]. * [@https://github.com/boostorg/container/issues/82 GitHub #82: ['"Function definition in header file"]]. * [@https://github.com/boostorg/container/issues/83 GitHub #83: ['"Iterator zero incrementing leads to assert on empty vector"]]. * [@https://github.com/boostorg/container/pull/84 GitHub #84: ['"Allow vector to be assigned to itself"]]. diff --git a/test/vector_test.cpp b/test/vector_test.cpp index 1e74451..903d3ea 100644 --- a/test/vector_test.cpp +++ b/test/vector_test.cpp @@ -56,6 +56,29 @@ int test_expand_bwd() return 0; } +struct X; + +template +struct XRef +{ + explicit XRef(T* ptr) noexcept : ptr(ptr) {} + operator T*() const noexcept { return ptr; } + T* ptr; +}; + +struct X +{ + XRef operator&() const noexcept { return XRef(this); } + XRef operator&() noexcept { return XRef(this); } +}; + + +bool test_smart_ref_type() +{ + boost::container::vector x(5); + return x.empty(); +} + class recursive_vector { public: @@ -184,6 +207,9 @@ int main() v.push_back(Test()); } + if (test_smart_ref_type()) + return 1; + //////////////////////////////////// // Backwards expansion test //////////////////////////////////// From cb21746b803bb8e2c0e7bf6d0deb62988a62eca3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Mon, 12 Nov 2018 22:52:45 +0100 Subject: [PATCH 09/12] Rewrite CTAD and SFINAE-out overloads as the standard requires --- include/boost/container/deque.hpp | 2 +- include/boost/container/detail/iterator.hpp | 13 + include/boost/container/detail/mpl.hpp | 31 +++ include/boost/container/detail/workaround.hpp | 7 + include/boost/container/flat_map.hpp | 225 +++++++++--------- include/boost/container/flat_set.hpp | 130 +++++++--- include/boost/container/list.hpp | 2 +- include/boost/container/map.hpp | 149 ++++++++---- include/boost/container/set.hpp | 129 +++++++--- include/boost/container/slist.hpp | 2 +- include/boost/container/stable_vector.hpp | 2 +- include/boost/container/string.hpp | 2 +- include/boost/container/vector.hpp | 2 +- test/deque_test.cpp | 2 +- test/flat_map_test.cpp | 106 +++++++-- test/flat_set_test.cpp | 131 ++++++++-- test/list_test.cpp | 2 +- test/map_test.cpp | 125 ++++++++-- test/set_test.cpp | 107 ++++++++- test/slist_test.cpp | 2 +- test/stable_vector_test.cpp | 2 +- test/string_test.cpp | 2 +- test/vector_test.cpp | 10 +- 23 files changed, 869 insertions(+), 316 deletions(-) diff --git a/include/boost/container/deque.hpp b/include/boost/container/deque.hpp index f04ba49..35cea2f 100644 --- a/include/boost/container/deque.hpp +++ b/include/boost/container/deque.hpp @@ -2238,7 +2238,7 @@ class deque : protected deque_base #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED }; -#if __cplusplus >= 201703L +#ifndef BOOST_CONTAINER_NO_CXX17_CTAD template deque(InputIterator, InputIterator) -> deque::value_type>; template diff --git a/include/boost/container/detail/iterator.hpp b/include/boost/container/detail/iterator.hpp index 2ceaf26..844f3fd 100644 --- a/include/boost/container/detail/iterator.hpp +++ b/include/boost/container/detail/iterator.hpp @@ -23,6 +23,7 @@ #include #include +#include namespace boost { namespace container { @@ -63,6 +64,18 @@ class back_emplacer back_emplacer& operator++(int){ return *this; } }; +#ifndef BOOST_CONTAINER_NO_CXX17_CTAD + +template +using it_based_non_const_first_type_t = typename dtl::remove_const::value_type::first_type>::type; + +template +using it_based_second_type_t = typename iterator_traits::value_type::second_type; + +template +using it_based_value_type_t = typename iterator_traits::value_type; + +#endif } //namespace container { } //namespace boost { diff --git a/include/boost/container/detail/mpl.hpp b/include/boost/container/detail/mpl.hpp index 5249dbf..4706c58 100644 --- a/include/boost/container/detail/mpl.hpp +++ b/include/boost/container/detail/mpl.hpp @@ -61,6 +61,7 @@ using boost::move_detail::enable_if_and; using boost::move_detail::disable_if_and; using boost::move_detail::enable_if_or; using boost::move_detail::disable_if_or; +using boost::move_detail::remove_const; template struct select1st @@ -102,6 +103,36 @@ struct enable_if_transparent : boost::move_detail::enable_if_c::value, R> {}; +#ifndef BOOST_CONTAINER_NO_CXX17_CTAD + +// void_t (void_t for C++11) +template using variadic_void_t = void; + +// Trait to detect Allocator-like types. +template +struct is_allocator +{ + static const bool value = false; +}; + +template +T&& ctad_declval(); + +template +struct is_allocator < Allocator, + variadic_void_t< typename Allocator::value_type + , decltype(ctad_declval().allocate(size_t{})) >> +{ + static const bool value = true; +}; + +template +using require_allocator_t = typename enable_if_c::value, T>::type; + +template +using require_nonallocator_t = typename enable_if_c::value, T>::type; + +#endif } //namespace dtl { } //namespace container { diff --git a/include/boost/container/detail/workaround.hpp b/include/boost/container/detail/workaround.hpp index 1fea112..4e49c0a 100644 --- a/include/boost/container/detail/workaround.hpp +++ b/include/boost/container/detail/workaround.hpp @@ -119,4 +119,11 @@ #define BOOST_CONTAINER_ASAN #endif + +#if (__cplusplus >= 201703L) +//CTAD supported +#else +#define BOOST_CONTAINER_NO_CXX17_CTAD +#endif + #endif //#ifndef BOOST_CONTAINER_DETAIL_WORKAROUND_HPP diff --git a/include/boost/container/flat_map.hpp b/include/boost/container/flat_map.hpp index e11522a..5cbbf9c 100644 --- a/include/boost/container/flat_map.hpp +++ b/include/boost/container/flat_map.hpp @@ -319,6 +319,21 @@ class flat_map : m_flat_tree(ordered_range, first, last, comp, dtl::force(a)) {} + //! Effects: Constructs an empty flat_map using the specified allocator and + //! inserts elements from the ordered range [first ,last). This function + //! is more efficient than the normal range creation for ordered ranges. + //! + //! Requires: [first ,last) must be ordered according to the predicate. + //! + //! Complexity: Linear in N. + //! + //! Note: Non-standard extension. + template + BOOST_CONTAINER_FORCEINLINE + flat_map(ordered_unique_range_t, InputIterator first, InputIterator last, const allocator_type& a) + : m_flat_tree(ordered_range, first, last, Compare(), a) + {} + #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) //! Effects: Constructs an empty flat_map and //! inserts elements from the range [il.begin() ,il.end()). @@ -1563,89 +1578,63 @@ class flat_map #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED }; -#if __cplusplus >= 201703L +#ifndef BOOST_CONTAINER_NO_CXX17_CTAD template flat_map(InputIterator, InputIterator) -> - flat_map< typename dtl::remove_const< typename iterator_traits::value_type::first_type>::type - , typename iterator_traits::value_type::second_type>; + flat_map< it_based_non_const_first_type_t + , it_based_second_type_t>; -#ifdef BOOST_HAS_CTAD_SFINAE - -namespace dtl { - - template - using enable_if_allocator_t = std::enable_if_t().allocate(0)), U *>, T>; - - template - using enable_if_compare_t = std::enable_if_t()(std::declval(), std::declval())), bool>, T>; - -} // namespace dtl - -template +template < typename InputIterator, typename Allocator + , typename = dtl::require_allocator_t> flat_map(InputIterator, InputIterator, Allocator const&) -> - flat_map< typename dtl::remove_const< typename iterator_traits::value_type::first_type>::type - , typename iterator_traits::value_type::second_type - , std::less::value_type::first_type>::type> - , dtl::enable_if_allocator_t::value_type>>>; + flat_map< it_based_non_const_first_type_t + , it_based_second_type_t + , std::less> + , Allocator>; -template +template < typename InputIterator, typename Compare + , typename = dtl::require_nonallocator_t> flat_map(InputIterator, InputIterator, Compare const&) -> - flat_map< typename dtl::remove_const::value_type::first_type>::type - , typename iterator_traits::value_type::second_type - , dtl::enable_if_compare_t::value_type::first_type>>>; - -#else - -template -flat_map(InputIterator, InputIterator, Compare const&) -> - flat_map< typename dtl::remove_const::value_type::first_type>::type - , typename iterator_traits::value_type::second_type + flat_map< it_based_non_const_first_type_t + , it_based_second_type_t , Compare>; -#endif - -template +template < typename InputIterator, typename Compare, typename Allocator + , typename = dtl::require_nonallocator_t + , typename = dtl::require_allocator_t> flat_map(InputIterator, InputIterator, Compare const&, Allocator const&) -> - flat_map< typename dtl::remove_const::value_type::first_type>::type - , typename iterator_traits::value_type::second_type + flat_map< it_based_non_const_first_type_t + , it_based_second_type_t , Compare , Allocator>; template flat_map(ordered_unique_range_t, InputIterator, InputIterator) -> - flat_map< typename dtl::remove_const::value_type::first_type>::type - , typename iterator_traits::value_type::second_type>; + flat_map< it_based_non_const_first_type_t + , it_based_second_type_t>; -#ifdef BOOST_HAS_CTAD_SFINAE - -template +template < typename InputIterator, typename Allocator + , typename = dtl::require_allocator_t> flat_map(ordered_unique_range_t, InputIterator, InputIterator, Allocator const&) -> - flat_map< typename dtl::remove_const::value_type::first_type>::type - , typename iterator_traits::value_type::second_type - , std::less::value_type::first_type>::type> - , dtl::enable_if_allocator_t::value_type>>>; + flat_map< it_based_non_const_first_type_t + , it_based_second_type_t + , std::less> + , Allocator>; -template +template < typename InputIterator, typename Compare + , typename = dtl::require_nonallocator_t> flat_map(ordered_unique_range_t, InputIterator, InputIterator, Compare const&) -> - flat_map< typename dtl::remove_const::value_type::first_type>::type - , typename iterator_traits::value_type::second_type - , dtl::enable_if_compare_t::value_type::first_type>>>; - -#else - -template -flat_map(ordered_unique_range_t, InputIterator, InputIterator, Compare const&) -> - flat_map< typename dtl::remove_const::value_type::first_type>::type - , typename iterator_traits::value_type::second_type + flat_map< it_based_non_const_first_type_t + , it_based_second_type_t , Compare>; -#endif - -template +template < typename InputIterator, typename Compare, typename Allocator + , typename = dtl::require_nonallocator_t + , typename = dtl::require_allocator_t> flat_map(ordered_unique_range_t, InputIterator, InputIterator, Compare const&, Allocator const&) -> - flat_map< typename dtl::remove_const::value_type::first_type>::type - , typename iterator_traits::value_type::second_type + flat_map< it_based_non_const_first_type_t + , it_based_second_type_t , Compare , Allocator>; @@ -1912,6 +1901,21 @@ class flat_multimap : m_flat_tree(ordered_range, first, last, comp, a) {} + //! Effects: Constructs an empty flat_multimap using the specified comparison object and + //! inserts elements from the ordered range [first ,last). This function + //! is more efficient than the normal range creation for ordered ranges. + //! + //! Requires: [first ,last) must be ordered according to the predicate. + //! + //! Complexity: Linear in N. + //! + //! Note: Non-standard extension. + template + BOOST_CONTAINER_FORCEINLINE + flat_multimap(ordered_range_t, InputIterator first, InputIterator last, const allocator_type &a) + : m_flat_tree(ordered_range, first, last, Compare(), a) + {} + #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) //! Effects: Constructs an empty flat_map and //! inserts elements from the range [il.begin(), il.end()). @@ -2880,82 +2884,65 @@ class flat_multimap { x.swap(y); } }; -#if __cplusplus >= 201703L +#ifndef BOOST_CONTAINER_NO_CXX17_CTAD template flat_multimap(InputIterator, InputIterator) -> - flat_multimap::value_type::first_type>::type - , typename iterator_traits::value_type::second_type>; + flat_multimap< it_based_non_const_first_type_t + , it_based_second_type_t>; -#ifdef BOOST_HAS_CTAD_SFINAE - -template +template < typename InputIterator, typename Allocator + , typename = dtl::require_allocator_t> flat_multimap(InputIterator, InputIterator, Allocator const&) -> - flat_multimap::value_type::first_type>::type - , typename iterator_traits::value_type::second_type - , std::less::value_type::first_type>::type> - , dtl::enable_if_allocator_t::value_type>>>; + flat_multimap< it_based_non_const_first_type_t + , it_based_second_type_t + , std::less> + , Allocator>; -template +template < typename InputIterator, typename Compare + , typename = dtl::require_nonallocator_t> flat_multimap(InputIterator, InputIterator, Compare const&) -> - flat_multimap< typename dtl::remove_const::value_type::first_type>::type - , typename iterator_traits::value_type::second_type - , dtl::enable_if_compare_t::value_type::first_type>>>; + flat_multimap< it_based_non_const_first_type_t + , it_based_second_type_t + , Compare>; -#else - -template -flat_multimap(InputIterator, InputIterator, Compare const&) -> - flat_multimap< typename dtl::remove_const::value_type::first_type>::type - , typename iterator_traits::value_type::second_type - , Compare>; - -#endif - -template +template < typename InputIterator, typename Compare, typename Allocator + , typename = dtl::require_nonallocator_t + , typename = dtl::require_allocator_t> flat_multimap(InputIterator, InputIterator, Compare const&, Allocator const&) -> - flat_multimap< typename dtl::remove_const::value_type::first_type>::type - , typename iterator_traits::value_type::second_type - , Compare - , Allocator>; + flat_multimap< it_based_non_const_first_type_t + , it_based_second_type_t + , Compare + , Allocator>; template flat_multimap(ordered_range_t, InputIterator, InputIterator) -> - flat_multimap< typename dtl::remove_const::value_type::first_type>::type - , typename iterator_traits::value_type::second_type>; + flat_multimap< it_based_non_const_first_type_t + , it_based_second_type_t>; -#ifdef BOOST_HAS_CTAD_SFINAE - -template +template < typename InputIterator, typename Allocator + , typename = dtl::require_allocator_t> flat_multimap(ordered_range_t, InputIterator, InputIterator, Allocator const&) -> - flat_multimap< typename dtl::remove_const::value_type::first_type>::type - , typename iterator_traits::value_type::second_type - , std::less::value_type::first_type>::type> - , dtl::enable_if_allocator_t::value_type>>>; + flat_multimap< it_based_non_const_first_type_t + , it_based_second_type_t + , std::less> + , Allocator>; -template +template < typename InputIterator, typename Compare + , typename = dtl::require_nonallocator_t> flat_multimap(ordered_range_t, InputIterator, InputIterator, Compare const&) -> - flat_multimap< typename dtl::remove_const::value_type::first_type>::type - , typename iterator_traits::value_type::second_type - , dtl::enable_if_compare_t::value_type::first_type>>>; + flat_multimap< it_based_non_const_first_type_t + , it_based_second_type_t + , Compare>; -#else - -template -flat_multimap(ordered_range_t, InputIterator, InputIterator, Compare const&) -> - flat_multimap< typename dtl::remove_const::value_type::first_type>::type - , typename iterator_traits::value_type::second_type - , Compare>; - -#endif - - -template +template < typename InputIterator, typename Compare, typename Allocator + , typename = dtl::require_nonallocator_t + , typename = dtl::require_allocator_t> flat_multimap(ordered_range_t, InputIterator, InputIterator, Compare const&, Allocator const&) -> - flat_multimap< typename dtl::remove_const::value_type::first_type>::type - , typename iterator_traits::value_type::second_type - , Compare - , Allocator>; + flat_multimap< it_based_non_const_first_type_t + , it_based_second_type_t + , Compare + , Allocator>; #endif diff --git a/include/boost/container/flat_set.hpp b/include/boost/container/flat_set.hpp index c4dd827..bd0b3cf 100644 --- a/include/boost/container/flat_set.hpp +++ b/include/boost/container/flat_set.hpp @@ -257,6 +257,22 @@ class flat_set : tree_t(ordered_unique_range, first, last, comp, a) {} + //! Effects: Constructs an empty container using the specified allocator and + //! inserts elements from the ordered unique range [first ,last). This function + //! is more efficient than the normal range creation for ordered ranges. + //! + //! Requires: [first ,last) must be ordered according to the predicate and must be + //! unique values. + //! + //! Complexity: Linear in N. + //! + //! Note: Non-standard extension. + template + BOOST_CONTAINER_FORCEINLINE + flat_set(ordered_unique_range_t, InputIterator first, InputIterator last, const allocator_type& a) + : tree_t(ordered_unique_range, first, last, Compare(), a) + {} + #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) //! Effects: Constructs an empty container and //! inserts elements from the range [il.begin(), il.end()). @@ -1108,39 +1124,57 @@ class flat_set #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED }; -#if __cplusplus >= 201703L +#ifndef BOOST_CONTAINER_NO_CXX17_CTAD template flat_set(InputIterator, InputIterator) -> - flat_set::value_type>; + flat_set< it_based_value_type_t >; -template +template < typename InputIterator, typename Allocator + , typename = dtl::require_allocator_t> flat_set(InputIterator, InputIterator, Allocator const&) -> - flat_set::value_type, std::less::value_type>, Allocator>; + flat_set< it_based_value_type_t + , std::less> + , Allocator>; -template +template < typename InputIterator, typename Compare + , typename = dtl::require_nonallocator_t> flat_set(InputIterator, InputIterator, Compare const&) -> - flat_set::value_type, Compare>; + flat_set< it_based_value_type_t + , Compare>; -template +template < typename InputIterator, typename Compare, typename Allocator + , typename = dtl::require_nonallocator_t + , typename = dtl::require_allocator_t> flat_set(InputIterator, InputIterator, Compare const&, Allocator const&) -> - flat_set::value_type, Compare, Allocator>; + flat_set< it_based_value_type_t + , Compare + , Allocator>; template flat_set(ordered_unique_range_t, InputIterator, InputIterator) -> - flat_set::value_type>; + flat_set< it_based_value_type_t>; -template +template < typename InputIterator, typename Allocator + , typename = dtl::require_allocator_t> flat_set(ordered_unique_range_t, InputIterator, InputIterator, Allocator const&) -> - flat_set::value_type, std::less::value_type>, Allocator>; + flat_set< it_based_value_type_t + , std::less> + , Allocator>; -template +template < typename InputIterator, typename Compare + , typename = dtl::require_nonallocator_t> flat_set(ordered_unique_range_t, InputIterator, InputIterator, Compare const&) -> - flat_set::value_type, Compare>; + flat_set< it_based_value_type_t + , Compare>; -template +template < typename InputIterator, typename Compare, typename Allocator + , typename = dtl::require_nonallocator_t + , typename = dtl::require_allocator_t> flat_set(ordered_unique_range_t, InputIterator, InputIterator, Compare const&, Allocator const&) -> - flat_set::value_type, Compare, Allocator>; + flat_set< it_based_value_type_t + , Compare + , Allocator>; #endif @@ -1320,6 +1354,20 @@ class flat_multiset : tree_t(ordered_range, first, last, comp, a) {} + //! Effects: Constructs an empty flat_multiset using the specified allocator and + //! inserts elements from the ordered range [first ,last ). This function + //! is more efficient than the normal range creation for ordered ranges. + //! + //! Requires: [first ,last) must be ordered according to the predicate. + //! + //! Complexity: Linear in N. + //! + //! Note: Non-standard extension. + template + BOOST_CONTAINER_FORCEINLINE flat_multiset(ordered_range_t, InputIterator first, InputIterator last, const allocator_type &a) + : tree_t(ordered_range, first, last, Compare(), a) + {} + #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) //! @copydoc ::boost::container::flat_set::flat_set(std::initializer_list il) @@ -1805,43 +1853,57 @@ class flat_multiset #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED }; -#if __cplusplus >= 201703L +#ifndef BOOST_CONTAINER_NO_CXX17_CTAD template flat_multiset(InputIterator, InputIterator) -> - flat_multiset::value_type>; + flat_multiset< it_based_value_type_t >; -template +template < typename InputIterator, typename Allocator + , typename = dtl::require_allocator_t> flat_multiset(InputIterator, InputIterator, Allocator const&) -> - flat_multiset< typename iterator_traits::value_type - , std::less::value_type> - , Allocator>; + flat_multiset< it_based_value_type_t + , std::less> + , Allocator>; -template +template < typename InputIterator, typename Compare + , typename = dtl::require_nonallocator_t> flat_multiset(InputIterator, InputIterator, Compare const&) -> - flat_multiset::value_type, Compare>; + flat_multiset< it_based_value_type_t + , Compare>; -template +template < typename InputIterator, typename Compare, typename Allocator + , typename = dtl::require_nonallocator_t + , typename = dtl::require_allocator_t> flat_multiset(InputIterator, InputIterator, Compare const&, Allocator const&) -> - flat_multiset::value_type, Compare, Allocator>; + flat_multiset< it_based_value_type_t + , Compare + , Allocator>; template flat_multiset(ordered_range_t, InputIterator, InputIterator) -> - flat_multiset::value_type>; + flat_multiset< it_based_value_type_t>; -template +template < typename InputIterator, typename Allocator + , typename = dtl::require_allocator_t> flat_multiset(ordered_range_t, InputIterator, InputIterator, Allocator const&) -> - flat_multiset< typename iterator_traits::value_type - , std::less::value_type> - , Allocator>; + flat_multiset< it_based_value_type_t + , std::less> + , Allocator>; -template +template < typename InputIterator, typename Compare + , typename = dtl::require_nonallocator_t> flat_multiset(ordered_range_t, InputIterator, InputIterator, Compare const&) -> - flat_multiset< typename iterator_traits::value_type, Compare>; + flat_multiset< it_based_value_type_t + , Compare>; -template +template < typename InputIterator, typename Compare, typename Allocator + , typename = dtl::require_nonallocator_t + , typename = dtl::require_allocator_t> flat_multiset(ordered_range_t, InputIterator, InputIterator, Compare const&, Allocator const&) -> - flat_multiset::value_type, Compare, Allocator>; + flat_multiset< it_based_value_type_t + , Compare + , Allocator>; #endif diff --git a/include/boost/container/list.hpp b/include/boost/container/list.hpp index 2e512f9..4be33fc 100644 --- a/include/boost/container/list.hpp +++ b/include/boost/container/list.hpp @@ -1498,7 +1498,7 @@ class list }; -#if __cplusplus >= 201703L +#ifndef BOOST_CONTAINER_NO_CXX17_CTAD template list(InputIterator, InputIterator) -> list::value_type>; diff --git a/include/boost/container/map.hpp b/include/boost/container/map.hpp index 02bd74f..98109ad 100644 --- a/include/boost/container/map.hpp +++ b/include/boost/container/map.hpp @@ -256,6 +256,22 @@ class map : base_t(ordered_range, first, last, comp, a) {} + //! Effects: Constructs an empty map using the specified allocator object and + //! inserts elements from the ordered unique range [first ,last). This function + //! is more efficient than the normal range creation for ordered ranges. + //! + //! Requires: [first ,last) must be ordered according to the predicate and must be + //! unique values. + //! + //! Complexity: Linear in N. + //! + //! Note: Non-standard extension. + template + BOOST_CONTAINER_FORCEINLINE map(ordered_unique_range_t, InputIterator first, InputIterator last, const allocator_type& a) + : base_t(ordered_range, first, last, Compare(), a) + {} + + #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) //! Effects: Constructs an empty map and //! inserts elements from the range [il.begin(), il.end()). @@ -1279,55 +1295,63 @@ class map #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED }; -#if __cplusplus >= 201703L +#ifndef BOOST_CONTAINER_NO_CXX17_CTAD template map(InputIterator, InputIterator) -> - map< typename dtl::remove_const< typename iterator_traits::value_type::first_type>::type - , typename iterator_traits::value_type::second_type>; + map< it_based_non_const_first_type_t + , it_based_second_type_t>; -template +template < typename InputIterator, typename Allocator + , typename = dtl::require_allocator_t> map(InputIterator, InputIterator, Allocator const&) -> - map< typename dtl::remove_const< typename iterator_traits::value_type::first_type>::type - , typename iterator_traits::value_type::second_type - , std::less::value_type::first_type>::type> + map< it_based_non_const_first_type_t + , it_based_second_type_t + , std::less> , Allocator>; -template +template < typename InputIterator, typename Compare + , typename = dtl::require_nonallocator_t> map(InputIterator, InputIterator, Compare const&) -> - map< typename dtl::remove_const::value_type::first_type>::type - , typename iterator_traits::value_type::second_type + map< it_based_non_const_first_type_t + , it_based_second_type_t , Compare>; -template +template < typename InputIterator, typename Compare, typename Allocator + , typename = dtl::require_nonallocator_t + , typename = dtl::require_allocator_t> map(InputIterator, InputIterator, Compare const&, Allocator const&) -> - map< typename dtl::remove_const::value_type::first_type>::type - , typename iterator_traits::value_type::second_type + map< it_based_non_const_first_type_t + , it_based_second_type_t , Compare , Allocator>; template map(ordered_unique_range_t, InputIterator, InputIterator) -> - map< typename dtl::remove_const::value_type::first_type>::type - , typename iterator_traits::value_type::second_type>; + map< it_based_non_const_first_type_t + , it_based_second_type_t>; -template +template < typename InputIterator, typename Allocator + , typename = dtl::require_allocator_t> map(ordered_unique_range_t, InputIterator, InputIterator, Allocator const&) -> - map< typename dtl::remove_const::value_type::first_type>::type - , typename iterator_traits::value_type::second_type - , std::less::value_type::first_type>::type> + map< it_based_non_const_first_type_t + , it_based_second_type_t + , std::less> , Allocator>; -template +template < typename InputIterator, typename Compare + , typename = dtl::require_nonallocator_t> map(ordered_unique_range_t, InputIterator, InputIterator, Compare const&) -> - map< typename dtl::remove_const::value_type::first_type>::type - , typename iterator_traits::value_type::second_type + map< it_based_non_const_first_type_t + , it_based_second_type_t , Compare>; -template +template < typename InputIterator, typename Compare, typename Allocator + , typename = dtl::require_nonallocator_t + , typename = dtl::require_allocator_t> map(ordered_unique_range_t, InputIterator, InputIterator, Compare const&, Allocator const&) -> - map< typename dtl::remove_const::value_type::first_type>::type - , typename iterator_traits::value_type::second_type + map< it_based_non_const_first_type_t + , it_based_second_type_t , Compare , Allocator>; @@ -1552,6 +1576,20 @@ class multimap : base_t(ordered_range, first, last, comp, a) {} + //! Effects: Constructs an empty multimap using the specified allocator and + //! inserts elements from the ordered range [first ,last). This function + //! is more efficient than the normal range creation for ordered ranges. + //! + //! Requires: [first ,last) must be ordered according to the predicate. + //! + //! Complexity: Linear in N. + //! + //! Note: Non-standard extension. + template + BOOST_CONTAINER_FORCEINLINE multimap(ordered_range_t, InputIterator first, InputIterator last, const allocator_type& a) + : base_t(ordered_range, first, last, Compare(), a) + {} + #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) //! Effects: Constructs an empty multimap and //! and inserts elements from the range [il.begin(), il.end()). @@ -2184,58 +2222,65 @@ class multimap #endif //#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) }; -#if __cplusplus >= 201703L +#ifndef BOOST_CONTAINER_NO_CXX17_CTAD template multimap(InputIterator, InputIterator) -> - multimap::value_type::first_type>::type - , typename iterator_traits::value_type::second_type>; + multimap< it_based_non_const_first_type_t + , it_based_second_type_t>; -template +template < typename InputIterator, typename Allocator + , typename = dtl::require_allocator_t> multimap(InputIterator, InputIterator, Allocator const&) -> - multimap::value_type::first_type>::type - , typename iterator_traits::value_type::second_type - , std::less::value_type::first_type>::type> - , Allocator>; + multimap< it_based_non_const_first_type_t + , it_based_second_type_t + , std::less> + , Allocator>; -template +template < typename InputIterator, typename Compare + , typename = dtl::require_nonallocator_t> multimap(InputIterator, InputIterator, Compare const&) -> - multimap< typename dtl::remove_const::value_type::first_type>::type - , typename iterator_traits::value_type::second_type + multimap< it_based_non_const_first_type_t + , it_based_second_type_t , Compare>; -template +template < typename InputIterator, typename Compare, typename Allocator + , typename = dtl::require_nonallocator_t + , typename = dtl::require_allocator_t> multimap(InputIterator, InputIterator, Compare const&, Allocator const&) -> - multimap< typename dtl::remove_const::value_type::first_type>::type - , typename iterator_traits::value_type::second_type + multimap< it_based_non_const_first_type_t + , it_based_second_type_t , Compare , Allocator>; template multimap(ordered_range_t, InputIterator, InputIterator) -> - multimap< typename dtl::remove_const::value_type::first_type>::type - , typename iterator_traits::value_type::second_type>; + multimap< it_based_non_const_first_type_t + , it_based_second_type_t>; -template +template < typename InputIterator, typename Allocator + , typename = dtl::require_allocator_t> multimap(ordered_range_t, InputIterator, InputIterator, Allocator const&) -> - multimap< typename dtl::remove_const::value_type::first_type>::type - , typename iterator_traits::value_type::second_type - , std::less::value_type::first_type>::type> + multimap< it_based_non_const_first_type_t + , it_based_second_type_t + , std::less> , Allocator>; -template +template < typename InputIterator, typename Compare + , typename = dtl::require_nonallocator_t> multimap(ordered_range_t, InputIterator, InputIterator, Compare const&) -> - multimap< typename dtl::remove_const::value_type::first_type>::type - , typename iterator_traits::value_type::second_type + multimap< it_based_non_const_first_type_t + , it_based_second_type_t , Compare>; -template +template < typename InputIterator, typename Compare, typename Allocator + , typename = dtl::require_nonallocator_t + , typename = dtl::require_allocator_t> multimap(ordered_range_t, InputIterator, InputIterator, Compare const&, Allocator const&) -> - multimap< typename dtl::remove_const::value_type::first_type>::type - , typename iterator_traits::value_type::second_type + multimap< it_based_non_const_first_type_t + , it_based_second_type_t , Compare , Allocator>; - #endif #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED diff --git a/include/boost/container/set.hpp b/include/boost/container/set.hpp index c2e6890..c985c7e 100644 --- a/include/boost/container/set.hpp +++ b/include/boost/container/set.hpp @@ -227,6 +227,21 @@ class set : base_t(ordered_range, first, last, comp, a) {} + //! Effects: Constructs an empty set using the specified allocator and + //! inserts elements from the ordered unique range [first ,last). This function + //! is more efficient than the normal range creation for ordered ranges. + //! + //! Requires: [first ,last) must be ordered according to the predicate and must be + //! unique values. + //! + //! Complexity: Linear in N. + //! + //! Note: Non-standard extension. + template + BOOST_CONTAINER_FORCEINLINE set(ordered_unique_range_t, InputIterator first, InputIterator last, const allocator_type& a) + : base_t(ordered_range, first, last, Compare(), a) + {} + #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) //! Effects: Constructs an empty set and //! inserts elements from the range [il.begin(), il.end()). @@ -944,39 +959,57 @@ class set #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED }; -#if __cplusplus >= 201703L +#ifndef BOOST_CONTAINER_NO_CXX17_CTAD template set(InputIterator, InputIterator) -> - set::value_type>; + set< it_based_value_type_t >; -template +template < typename InputIterator, typename Allocator + , typename = dtl::require_allocator_t> set(InputIterator, InputIterator, Allocator const&) -> - set::value_type, std::less::value_type>, Allocator>; + set< it_based_value_type_t + , std::less> + , Allocator>; -template +template < typename InputIterator, typename Compare + , typename = dtl::require_nonallocator_t> set(InputIterator, InputIterator, Compare const&) -> - set::value_type, Compare>; + set< it_based_value_type_t + , Compare>; -template +template < typename InputIterator, typename Compare, typename Allocator + , typename = dtl::require_nonallocator_t + , typename = dtl::require_allocator_t> set(InputIterator, InputIterator, Compare const&, Allocator const&) -> - set::value_type, Compare, Allocator>; + set< it_based_value_type_t + , Compare + , Allocator>; template set(ordered_unique_range_t, InputIterator, InputIterator) -> - set::value_type>; + set< it_based_value_type_t>; -template +template < typename InputIterator, typename Allocator + , typename = dtl::require_allocator_t> set(ordered_unique_range_t, InputIterator, InputIterator, Allocator const&) -> - set::value_type, std::less::value_type>, Allocator>; + set< it_based_value_type_t + , std::less> + , Allocator>; -template +template < typename InputIterator, typename Compare + , typename = dtl::require_nonallocator_t> set(ordered_unique_range_t, InputIterator, InputIterator, Compare const&) -> - set::value_type, Compare>; + set< it_based_value_type_t + , Compare>; -template +template < typename InputIterator, typename Compare, typename Allocator + , typename = dtl::require_nonallocator_t + , typename = dtl::require_allocator_t> set(ordered_unique_range_t, InputIterator, InputIterator, Compare const&, Allocator const&) -> - set::value_type, Compare, Allocator>; + set< it_based_value_type_t + , Compare + , Allocator>; #endif @@ -1150,6 +1183,20 @@ class multiset : base_t(ordered_range, first, last, comp, a) {} + //! Effects: Constructs an empty multiset using the specified allocator and + //! inserts elements from the ordered range [first ,last ). This function + //! is more efficient than the normal range creation for ordered ranges. + //! + //! Requires: [first ,last) must be ordered according to the predicate. + //! + //! Complexity: Linear in N. + //! + //! Note: Non-standard extension. + template + BOOST_CONTAINER_FORCEINLINE multiset(ordered_range_t, InputIterator first, InputIterator last, const allocator_type &a) + : base_t(ordered_range, first, last, Compare(), a) + {} + #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) //! @copydoc ::boost::container::set::set(std::initializer_list) BOOST_CONTAINER_FORCEINLINE multiset(std::initializer_list il) @@ -1573,43 +1620,57 @@ class multiset #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED }; -#if __cplusplus >= 201703L +#ifndef BOOST_CONTAINER_NO_CXX17_CTAD template multiset(InputIterator, InputIterator) -> - multiset::value_type>; + multiset< it_based_value_type_t >; -template +template < typename InputIterator, typename Allocator + , typename = dtl::require_allocator_t> multiset(InputIterator, InputIterator, Allocator const&) -> - multiset< typename iterator_traits::value_type - , std::less::value_type> - , Allocator>; + multiset< it_based_value_type_t + , std::less> + , Allocator>; -template +template < typename InputIterator, typename Compare + , typename = dtl::require_nonallocator_t> multiset(InputIterator, InputIterator, Compare const&) -> - multiset::value_type, Compare>; + multiset< it_based_value_type_t + , Compare>; -template +template < typename InputIterator, typename Compare, typename Allocator + , typename = dtl::require_nonallocator_t + , typename = dtl::require_allocator_t> multiset(InputIterator, InputIterator, Compare const&, Allocator const&) -> - multiset::value_type, Compare, Allocator>; + multiset< it_based_value_type_t + , Compare + , Allocator>; template multiset(ordered_range_t, InputIterator, InputIterator) -> - multiset::value_type>; + multiset< it_based_value_type_t>; -template +template < typename InputIterator, typename Allocator + , typename = dtl::require_allocator_t> multiset(ordered_range_t, InputIterator, InputIterator, Allocator const&) -> - multiset< typename iterator_traits::value_type - , std::less::value_type> - , Allocator>; + multiset< it_based_value_type_t + , std::less> + , Allocator>; -template +template < typename InputIterator, typename Compare + , typename = dtl::require_nonallocator_t> multiset(ordered_range_t, InputIterator, InputIterator, Compare const&) -> - multiset< typename iterator_traits::value_type, Compare>; + multiset< it_based_value_type_t + , Compare>; -template +template < typename InputIterator, typename Compare, typename Allocator + , typename = dtl::require_nonallocator_t + , typename = dtl::require_allocator_t> multiset(ordered_range_t, InputIterator, InputIterator, Compare const&, Allocator const&) -> - multiset::value_type, Compare, Allocator>; + multiset< it_based_value_type_t + , Compare + , Allocator>; #endif diff --git a/include/boost/container/slist.hpp b/include/boost/container/slist.hpp index 2bdf843..6310f58 100644 --- a/include/boost/container/slist.hpp +++ b/include/boost/container/slist.hpp @@ -1668,7 +1668,7 @@ class slist #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED }; -#if __cplusplus >= 201703L +#ifndef BOOST_CONTAINER_NO_CXX17_CTAD template slist(InpIt, InpIt) -> diff --git a/include/boost/container/stable_vector.hpp b/include/boost/container/stable_vector.hpp index cf7a0ef..1f55c43 100644 --- a/include/boost/container/stable_vector.hpp +++ b/include/boost/container/stable_vector.hpp @@ -2142,7 +2142,7 @@ class stable_vector #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED }; -#if __cplusplus >= 201703L +#ifndef BOOST_CONTAINER_NO_CXX17_CTAD template stable_vector(InputIterator, InputIterator) -> diff --git a/include/boost/container/string.hpp b/include/boost/container/string.hpp index 99120a1..ca51cfd 100644 --- a/include/boost/container/string.hpp +++ b/include/boost/container/string.hpp @@ -2978,7 +2978,7 @@ class basic_string #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED }; -#if __cplusplus >= 201703L +#ifndef BOOST_CONTAINER_NO_CXX17_CTAD template basic_string(InputIterator, InputIterator) -> diff --git a/include/boost/container/vector.hpp b/include/boost/container/vector.hpp index aa4b505..939b62f 100644 --- a/include/boost/container/vector.hpp +++ b/include/boost/container/vector.hpp @@ -3370,7 +3370,7 @@ class vector #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED }; -#if __cplusplus >= 201703L +#ifndef BOOST_CONTAINER_NO_CXX17_CTAD template vector(InputIterator, InputIterator) -> diff --git a/test/deque_test.cpp b/test/deque_test.cpp index 86173db..01c47e0 100644 --- a/test/deque_test.cpp +++ b/test/deque_test.cpp @@ -268,7 +268,7 @@ bool do_test() if(!test::CheckEqualContainers(cntdeque, stddeque)) return 1; } -#if __cplusplus >= 201703L +#ifndef BOOST_CONTAINER_NO_CXX17_CTAD //Check Constructor Template Auto Deduction { auto gold = MyStdDeque{ 1, 2, 3 }; diff --git a/test/flat_map_test.cpp b/test/flat_map_test.cpp index bd7af01..f1cc06b 100644 --- a/test/flat_map_test.cpp +++ b/test/flat_map_test.cpp @@ -178,28 +178,98 @@ bool flat_tree_ordered_insertion_test() bool constructor_template_auto_deduction_test() { -#if __cplusplus >= 201703L + +#ifndef BOOST_CONTAINER_NO_CXX17_CTAD using namespace boost::container; const std::size_t NumElements = 100; - //Ordered insertion map { std::map int_map; for(std::size_t i = 0; i != NumElements; ++i){ int_map.insert(std::map::value_type(static_cast(i), static_cast(i))); } - //Construction insertion - auto fmap = flat_map(ordered_unique_range, int_map.begin(), int_map.end()); - if(!CheckEqualContainers(int_map, fmap)) - return false; - std::multimap int_mmap; - for(std::size_t i = 0; i != NumElements; ++i){ + for (std::size_t i = 0; i != NumElements; ++i) { int_mmap.insert(std::multimap::value_type(static_cast(i), static_cast(i))); } - //Construction insertion - auto fmmap = flat_multimap(ordered_range, int_mmap.begin(), int_mmap.end()); - if(!CheckEqualContainers(int_mmap, fmmap)) - return false; + + typedef std::less comp_int_t; + typedef std::allocator > alloc_pair_int_t; + + //range + { + auto fmap = flat_map(int_map.begin(), int_map.end()); + if (!CheckEqualContainers(int_map, fmap)) + return false; + auto fmmap = flat_multimap(int_mmap.begin(), int_mmap.end()); + if (!CheckEqualContainers(int_mmap, fmmap)) + return false; + } + //range+comp + { + auto fmap = flat_map(int_map.begin(), int_map.end(), comp_int_t()); + if (!CheckEqualContainers(int_map, fmap)) + return false; + auto fmmap = flat_multimap(int_mmap.begin(), int_mmap.end(), comp_int_t()); + if (!CheckEqualContainers(int_mmap, fmmap)) + return false; + } + //range+comp+alloc + { + auto fmap = flat_map(int_map.begin(), int_map.end(), comp_int_t(), alloc_pair_int_t()); + if (!CheckEqualContainers(int_map, fmap)) + return false; + auto fmmap = flat_multimap(int_mmap.begin(), int_mmap.end(), comp_int_t(), alloc_pair_int_t()); + if (!CheckEqualContainers(int_mmap, fmmap)) + return false; + } + //range+alloc + { + auto fmap = flat_map(int_map.begin(), int_map.end(), alloc_pair_int_t()); + if (!CheckEqualContainers(int_map, fmap)) + return false; + auto fmmap = flat_multimap(int_mmap.begin(), int_mmap.end(), alloc_pair_int_t()); + if (!CheckEqualContainers(int_mmap, fmmap)) + return false; + } + + //ordered_unique_range / ordered_range + + //range + { + auto fmap = flat_map(ordered_unique_range, int_map.begin(), int_map.end()); + if(!CheckEqualContainers(int_map, fmap)) + return false; + auto fmmap = flat_multimap(ordered_range, int_mmap.begin(), int_mmap.end()); + if(!CheckEqualContainers(int_mmap, fmmap)) + return false; + } + //range+comp + { + auto fmap = flat_map(ordered_unique_range, int_map.begin(), int_map.end(), comp_int_t()); + if (!CheckEqualContainers(int_map, fmap)) + return false; + auto fmmap = flat_multimap(ordered_range, int_mmap.begin(), int_mmap.end(), comp_int_t()); + if (!CheckEqualContainers(int_mmap, fmmap)) + return false; + } + //range+comp+alloc + { + auto fmap = flat_map(ordered_unique_range, int_map.begin(), int_map.end(), comp_int_t(), alloc_pair_int_t()); + if (!CheckEqualContainers(int_map, fmap)) + return false; + auto fmmap = flat_multimap(ordered_range, int_mmap.begin(), int_mmap.end(), comp_int_t(), alloc_pair_int_t()); + if (!CheckEqualContainers(int_mmap, fmmap)) + return false; + } + //range+alloc + { + auto fmap = flat_map(ordered_unique_range, int_map.begin(), int_map.end(),alloc_pair_int_t()); + if (!CheckEqualContainers(int_map, fmap)) + return false; + auto fmmap = flat_multimap(ordered_range, int_mmap.begin(), int_mmap.end(),alloc_pair_int_t()); + if (!CheckEqualContainers(int_mmap, fmmap)) + return false; + } } #endif @@ -476,7 +546,7 @@ bool test_heterogeneous_lookups() int main() { using namespace boost::container::test; -/* + //Allocator argument container { flat_map map_((flat_map::allocator_type())); @@ -530,7 +600,7 @@ int main() if (!test_heterogeneous_lookups()) return 1; -*/ + //////////////////////////////////// // Testing allocator implementations //////////////////////////////////// @@ -546,7 +616,7 @@ int main() std::cout << "Error in map_test >" << std::endl; return 1; } - /* + if (0 != test::map_test < GetMapContainer >::apply::map_type , MyStdMap @@ -581,9 +651,9 @@ int main() , MyStdMultiMap>()) { std::cout << "Error in map_test >" << std::endl; return 1; - }*/ + } } -/* + if(!boost::container::test::test_map_support_for_initialization_list_for >()) return 1; @@ -628,7 +698,7 @@ int main() return 1; } } -*/ + return 0; } diff --git a/test/flat_set_test.cpp b/test/flat_set_test.cpp index 753c074..7e561f7 100644 --- a/test/flat_set_test.cpp +++ b/test/flat_set_test.cpp @@ -276,6 +276,106 @@ bool flat_tree_ordered_insertion_test() return true; } +bool constructor_template_auto_deduction_test() +{ + +#ifndef BOOST_CONTAINER_NO_CXX17_CTAD + using namespace boost::container; + const std::size_t NumElements = 100; + { + std::set int_set; + for (std::size_t i = 0; i != NumElements; ++i) { + int_set.insert(static_cast(i)); + } + std::multiset int_mset; + for (std::size_t i = 0; i != NumElements; ++i) { + int_mset.insert(static_cast(i)); + } + + typedef std::less comp_int_t; + typedef std::allocator alloc_int_t; + + //range + { + auto fset = flat_set(int_set.begin(), int_set.end()); + if (!CheckEqualContainers(int_set, fset)) + return false; + auto fmset = flat_multiset(int_mset.begin(), int_mset.end()); + if (!CheckEqualContainers(int_mset, fmset)) + return false; + } + //range+comp + { + auto fset = flat_set(int_set.begin(), int_set.end(), comp_int_t()); + if (!CheckEqualContainers(int_set, fset)) + return false; + auto fmset = flat_multiset(int_mset.begin(), int_mset.end(), comp_int_t()); + if (!CheckEqualContainers(int_mset, fmset)) + return false; + } + //range+comp+alloc + { + auto fset = flat_set(int_set.begin(), int_set.end(), comp_int_t(), alloc_int_t()); + if (!CheckEqualContainers(int_set, fset)) + return false; + auto fmset = flat_multiset(int_mset.begin(), int_mset.end(), comp_int_t(), alloc_int_t()); + if (!CheckEqualContainers(int_mset, fmset)) + return false; + } + //range+alloc + { + auto fset = flat_set(int_set.begin(), int_set.end(), alloc_int_t()); + if (!CheckEqualContainers(int_set, fset)) + return false; + auto fmset = flat_multiset(int_mset.begin(), int_mset.end(), alloc_int_t()); + if (!CheckEqualContainers(int_mset, fmset)) + return false; + } + + //ordered_unique_range / ordered_range + + //range + { + auto fset = flat_set(ordered_unique_range, int_set.begin(), int_set.end()); + if (!CheckEqualContainers(int_set, fset)) + return false; + auto fmset = flat_multiset(ordered_range, int_mset.begin(), int_mset.end()); + if (!CheckEqualContainers(int_mset, fmset)) + return false; + } + //range+comp + { + auto fset = flat_set(ordered_unique_range, int_set.begin(), int_set.end(), comp_int_t()); + if (!CheckEqualContainers(int_set, fset)) + return false; + auto fmset = flat_multiset(ordered_range, int_mset.begin(), int_mset.end(), comp_int_t()); + if (!CheckEqualContainers(int_mset, fmset)) + return false; + } + //range+comp+alloc + { + auto fset = flat_set(ordered_unique_range, int_set.begin(), int_set.end(), comp_int_t(), alloc_int_t()); + if (!CheckEqualContainers(int_set, fset)) + return false; + auto fmset = flat_multiset(ordered_range, int_mset.begin(), int_mset.end(), comp_int_t(), alloc_int_t()); + if (!CheckEqualContainers(int_mset, fmset)) + return false; + } + //range+alloc + { + auto fset = flat_set(ordered_unique_range, int_set.begin(), int_set.end(), alloc_int_t()); + if (!CheckEqualContainers(int_set, fset)) + return false; + auto fmset = flat_multiset(ordered_range, int_mset.begin(), int_mset.end(), alloc_int_t()); + if (!CheckEqualContainers(int_mset, fmset)) + return false; + } + } +#endif + + return true; +} + template< class RandomIt > void random_shuffle( RandomIt first, RandomIt last ) { @@ -594,6 +694,13 @@ int main() return 1; } + //////////////////////////////////// + // Constructor Template Auto Deduction test + //////////////////////////////////// + if (!constructor_template_auto_deduction_test()) { + return 1; + } + //////////////////////////////////// // Extract/Adopt test //////////////////////////////////// @@ -706,30 +813,6 @@ int main() } } -#if __cplusplus >= 201703L - //////////////////////////////////// - // Constructor Template Auto Deduction - //////////////////////////////////// - { - auto gold = std::set({ 1, 2, 3 }); - auto test = boost::container::flat_set(gold.begin(), gold.end()); - if (test.size() != 3) - return 1; - test = boost::container::flat_set(ordered_unique_range, gold.begin(), gold.end()); - if (test.size() != 3) - return 1; - } - { - auto gold = std::multiset({ 1, 2, 3 }); - auto test = boost::container::flat_multiset(gold.begin(), gold.end()); - if (test.size() != 3) - return 1; - test = boost::container::flat_multiset(ordered_range, gold.begin(), gold.end()); - if (test.size() != 3) - return 1; - } -#endif - return 0; } diff --git a/test/list_test.cpp b/test/list_test.cpp index 8348725..5006a7d 100644 --- a/test/list_test.cpp +++ b/test/list_test.cpp @@ -214,7 +214,7 @@ int main () } } -#if __cplusplus >= 201703L +#ifndef BOOST_CONTAINER_NO_CXX17_CTAD //////////////////////////////////// // Constructor Template Auto Deduction Tests //////////////////////////////////// diff --git a/test/map_test.cpp b/test/map_test.cpp index ca323f2..90998f0 100644 --- a/test/map_test.cpp +++ b/test/map_test.cpp @@ -337,6 +337,106 @@ bool test_heterogeneous_lookups() return true; } +bool constructor_template_auto_deduction_test() +{ + +#ifndef BOOST_CONTAINER_NO_CXX17_CTAD + using namespace boost::container; + const std::size_t NumElements = 100; + { + std::map int_map; + for(std::size_t i = 0; i != NumElements; ++i){ + int_map.insert(std::map::value_type(static_cast(i), static_cast(i))); + } + std::multimap int_mmap; + for (std::size_t i = 0; i != NumElements; ++i) { + int_mmap.insert(std::multimap::value_type(static_cast(i), static_cast(i))); + } + + typedef std::less comp_int_t; + typedef std::allocator > alloc_pair_int_t; + + //range + { + auto fmap = map(int_map.begin(), int_map.end()); + if (!CheckEqualContainers(int_map, fmap)) + return false; + auto fmmap = multimap(int_mmap.begin(), int_mmap.end()); + if (!CheckEqualContainers(int_mmap, fmmap)) + return false; + } + //range+comp + { + auto fmap = map(int_map.begin(), int_map.end(), comp_int_t()); + if (!CheckEqualContainers(int_map, fmap)) + return false; + auto fmmap = multimap(int_mmap.begin(), int_mmap.end(), comp_int_t()); + if (!CheckEqualContainers(int_mmap, fmmap)) + return false; + } + //range+comp+alloc + { + auto fmap = map(int_map.begin(), int_map.end(), comp_int_t(), alloc_pair_int_t()); + if (!CheckEqualContainers(int_map, fmap)) + return false; + auto fmmap = multimap(int_mmap.begin(), int_mmap.end(), comp_int_t(), alloc_pair_int_t()); + if (!CheckEqualContainers(int_mmap, fmmap)) + return false; + } + //range+alloc + { + auto fmap = map(int_map.begin(), int_map.end(), alloc_pair_int_t()); + if (!CheckEqualContainers(int_map, fmap)) + return false; + auto fmmap = multimap(int_mmap.begin(), int_mmap.end(), alloc_pair_int_t()); + if (!CheckEqualContainers(int_mmap, fmmap)) + return false; + } + + //ordered_unique_range / ordered_range + + //range + { + auto fmap = map(ordered_unique_range, int_map.begin(), int_map.end()); + if(!CheckEqualContainers(int_map, fmap)) + return false; + auto fmmap = multimap(ordered_range, int_mmap.begin(), int_mmap.end()); + if(!CheckEqualContainers(int_mmap, fmmap)) + return false; + } + //range+comp + { + auto fmap = map(ordered_unique_range, int_map.begin(), int_map.end(), comp_int_t()); + if (!CheckEqualContainers(int_map, fmap)) + return false; + auto fmmap = multimap(ordered_range, int_mmap.begin(), int_mmap.end(), comp_int_t()); + if (!CheckEqualContainers(int_mmap, fmmap)) + return false; + } + //range+comp+alloc + { + auto fmap = map(ordered_unique_range, int_map.begin(), int_map.end(), comp_int_t(), alloc_pair_int_t()); + if (!CheckEqualContainers(int_map, fmap)) + return false; + auto fmmap = multimap(ordered_range, int_mmap.begin(), int_mmap.end(), comp_int_t(), alloc_pair_int_t()); + if (!CheckEqualContainers(int_mmap, fmmap)) + return false; + } + //range+alloc + { + auto fmap = map(ordered_unique_range, int_map.begin(), int_map.end(),alloc_pair_int_t()); + if (!CheckEqualContainers(int_map, fmap)) + return false; + auto fmmap = multimap(ordered_range, int_mmap.begin(), int_mmap.end(),alloc_pair_int_t()); + if (!CheckEqualContainers(int_mmap, fmmap)) + return false; + } + } +#endif + + return true; +} + }}} //namespace boost::container::test int main () @@ -474,30 +574,19 @@ int main () } } -#if __cplusplus >= 201703L - //////////////////////////////////// - // Constructor Template Auto Deduction - //////////////////////////////////// - { - auto gold = std::map({ {1,1}, {2,2}, {3,3} } ); - auto test = boost::container::map(gold.begin(), gold.end()); - if (test.size() != 3) - return 1; - } - { - auto gold = std::multimap({ {1,1}, {2,2}, {3,3} } ); - auto test = boost::container::multimap(gold.begin(), gold.end()); - if (test.size() != 3) - return 1; - } -#endif - //////////////////////////////////// // Node extraction/insertion testing functions //////////////////////////////////// if(!node_type_test()) return 1; + //////////////////////////////////// + // Constructor Template Auto Deduction test + //////////////////////////////////// + if (!test::constructor_template_auto_deduction_test()) { + return 1; + } + if (!boost::container::test::instantiate_constructors, multimap >()) return 1; diff --git a/test/set_test.cpp b/test/set_test.cpp index 33cc0a4..9164222 100644 --- a/test/set_test.cpp +++ b/test/set_test.cpp @@ -206,6 +206,104 @@ struct alloc_propagate_base }; }; +bool constructor_template_auto_deduction_test() +{ +#ifndef BOOST_CONTAINER_NO_CXX17_CTAD + using namespace boost::container; + const std::size_t NumElements = 100; + { + std::set int_set; + for (std::size_t i = 0; i != NumElements; ++i) { + int_set.insert(static_cast(i)); + } + std::multiset int_mset; + for (std::size_t i = 0; i != NumElements; ++i) { + int_mset.insert(static_cast(i)); + } + + typedef std::less comp_int_t; + typedef std::allocator alloc_int_t; + + //range + { + auto fset = set(int_set.begin(), int_set.end()); + if (!CheckEqualContainers(int_set, fset)) + return false; + auto fmset = multiset(int_mset.begin(), int_mset.end()); + if (!CheckEqualContainers(int_mset, fmset)) + return false; + } + //range+comp + { + auto fset = set(int_set.begin(), int_set.end(), comp_int_t()); + if (!CheckEqualContainers(int_set, fset)) + return false; + auto fmset = multiset(int_mset.begin(), int_mset.end(), comp_int_t()); + if (!CheckEqualContainers(int_mset, fmset)) + return false; + } + //range+comp+alloc + { + auto fset = set(int_set.begin(), int_set.end(), comp_int_t(), alloc_int_t()); + if (!CheckEqualContainers(int_set, fset)) + return false; + auto fmset = multiset(int_mset.begin(), int_mset.end(), comp_int_t(), alloc_int_t()); + if (!CheckEqualContainers(int_mset, fmset)) + return false; + } + //range+alloc + { + auto fset = set(int_set.begin(), int_set.end(), alloc_int_t()); + if (!CheckEqualContainers(int_set, fset)) + return false; + auto fmset = multiset(int_mset.begin(), int_mset.end(), alloc_int_t()); + if (!CheckEqualContainers(int_mset, fmset)) + return false; + } + + //ordered_unique_range / ordered_range + + //range + { + auto fset = set(ordered_unique_range, int_set.begin(), int_set.end()); + if (!CheckEqualContainers(int_set, fset)) + return false; + auto fmset = multiset(ordered_range, int_mset.begin(), int_mset.end()); + if (!CheckEqualContainers(int_mset, fmset)) + return false; + } + //range+comp + { + auto fset = set(ordered_unique_range, int_set.begin(), int_set.end(), comp_int_t()); + if (!CheckEqualContainers(int_set, fset)) + return false; + auto fmset = multiset(ordered_range, int_mset.begin(), int_mset.end(), comp_int_t()); + if (!CheckEqualContainers(int_mset, fmset)) + return false; + } + //range+comp+alloc + { + auto fset = set(ordered_unique_range, int_set.begin(), int_set.end(), comp_int_t(), alloc_int_t()); + if (!CheckEqualContainers(int_set, fset)) + return false; + auto fmset = multiset(ordered_range, int_mset.begin(), int_mset.end(), comp_int_t(), alloc_int_t()); + if (!CheckEqualContainers(int_mset, fmset)) + return false; + } + //range+alloc + { + auto fset = set(ordered_unique_range, int_set.begin(), int_set.end(), alloc_int_t()); + if (!CheckEqualContainers(int_set, fset)) + return false; + auto fmset = multiset(ordered_range, int_mset.begin(), int_mset.end(), alloc_int_t()); + if (!CheckEqualContainers(int_mset, fmset)) + return false; + } + } +#endif + return true; +} + }}} //boost::container::test template @@ -360,6 +458,13 @@ int main () test_merge_from_different_comparison(); + //////////////////////////////////// + // Constructor Template Auto Deduction test + //////////////////////////////////// + if (!test::constructor_template_auto_deduction_test()) { + return 1; + } + if(!test_heterogeneous_lookups()) return 1; @@ -500,7 +605,7 @@ int main () if(!node_type_test()) return 1; -#if __cplusplus >= 201703L +#ifndef BOOST_CONTAINER_NO_CXX17_CTAD //////////////////////////////////// // Constructor Template Auto Deduction //////////////////////////////////// diff --git a/test/slist_test.cpp b/test/slist_test.cpp index 543eba1..4e09837 100644 --- a/test/slist_test.cpp +++ b/test/slist_test.cpp @@ -217,7 +217,7 @@ int main () return 1; } } -#if __cplusplus >= 201703L +#ifndef BOOST_CONTAINER_NO_CXX17_CTAD //////////////////////////////////// // Constructor Template Auto Deduction Tests //////////////////////////////////// diff --git a/test/stable_vector_test.cpp b/test/stable_vector_test.cpp index 7fb1014..fd76330 100644 --- a/test/stable_vector_test.cpp +++ b/test/stable_vector_test.cpp @@ -177,7 +177,7 @@ int main() } } -#if __cplusplus >= 201703L +#ifndef BOOST_CONTAINER_NO_CXX17_CTAD //////////////////////////////////// // Constructor Template Auto Deduction testing //////////////////////////////////// diff --git a/test/string_test.cpp b/test/string_test.cpp index 4c15fe6..2dfb2a4 100644 --- a/test/string_test.cpp +++ b/test/string_test.cpp @@ -456,7 +456,7 @@ int string_test() return 1; } -#if __cplusplus >= 201703L +#ifndef BOOST_CONTAINER_NO_CXX17_CTAD //Chect Constructor Template Auto Deduction { auto gold = StdString(string_literals::String()); diff --git a/test/vector_test.cpp b/test/vector_test.cpp index 903d3ea..84a7569 100644 --- a/test/vector_test.cpp +++ b/test/vector_test.cpp @@ -61,15 +61,15 @@ struct X; template struct XRef { - explicit XRef(T* ptr) noexcept : ptr(ptr) {} - operator T*() const noexcept { return ptr; } + explicit XRef(T* ptr) : ptr(ptr) {} + operator T*() const { return ptr; } T* ptr; }; struct X { - XRef operator&() const noexcept { return XRef(this); } - XRef operator&() noexcept { return XRef(this); } + XRef operator&() const { return XRef(this); } + XRef operator&() { return XRef(this); } }; @@ -260,7 +260,7 @@ int main() } } -#if __cplusplus >= 201703L +#ifndef BOOST_CONTAINER_NO_CXX17_CTAD //////////////////////////////////// // Constructor Template Auto Deduction testing //////////////////////////////////// From d99bbe1dcc0f3030783120b032289ed2d9136c27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Mon, 12 Nov 2018 22:57:24 +0100 Subject: [PATCH 10/12] Update changelog with Issue #80 --- doc/container.qbk | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/container.qbk b/doc/container.qbk index 70b4273..637bdeb 100644 --- a/doc/container.qbk +++ b/doc/container.qbk @@ -1254,6 +1254,7 @@ use [*Boost.Container]? There are several reasons for that: * Fixed bugs: * [@https://github.com/boostorg/container/issues/77 GitHub #77: ['"warning: 'sbrk' is deprecated"]]. * [@https://github.com/boostorg/container/issues/79 GitHub #79: ['"Mark small_vector move operations noexcept"]]. + * [@https://github.com/boostorg/container/issues/80 GitHub #80: ['"flat_map deduction guides are ambiguous"]]. * [@https://github.com/boostorg/container/issues/81 GitHub #81: ['"Vector with custom allocator does not support value types with operator&"]]. * [@https://github.com/boostorg/container/issues/82 GitHub #82: ['"Function definition in header file"]]. * [@https://github.com/boostorg/container/issues/83 GitHub #83: ['"Iterator zero incrementing leads to assert on empty vector"]]. From be2ff22a825855813c8e79c287e037d1dce66c7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Tue, 13 Nov 2018 22:19:30 +0100 Subject: [PATCH 11/12] Fix GitHub #90 ("UBSAN failures detected in preflight CI PR") --- doc/container.qbk | 2 ++ .../container/detail/multiallocation_chain.hpp | 15 ++++++++++----- include/boost/container/pmr/resource_adaptor.hpp | 2 +- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/doc/container.qbk b/doc/container.qbk index 637bdeb..2061f27 100644 --- a/doc/container.qbk +++ b/doc/container.qbk @@ -1261,6 +1261,8 @@ use [*Boost.Container]? There are several reasons for that: * [@https://github.com/boostorg/container/pull/84 GitHub #84: ['"Allow vector to be assigned to itself"]]. * [@https://github.com/boostorg/container/pull/85 GitHub #85: ['"container: misc-typos"]]. * [@https://github.com/boostorg/container/pull/86 GitHub #86: ['"Add missing warning re-enabling include"]]. + * [@https://github.com/boostorg/container/issues/90 GitHub #90: ['"UBSAN failures detected in preflight CI PR "]]. + [endsect] diff --git a/include/boost/container/detail/multiallocation_chain.hpp b/include/boost/container/detail/multiallocation_chain.hpp index bc3b285..c7d94f4 100644 --- a/include/boost/container/detail/multiallocation_chain.hpp +++ b/include/boost/container/detail/multiallocation_chain.hpp @@ -171,11 +171,16 @@ class basic_multiallocation_chain std::pair extract_data() { - std::pair ret - (slist_impl_.begin().operator->() - ,slist_impl_.last().operator->()); - slist_impl_.clear(); - return ret; + if(BOOST_LIKELY(!slist_impl_.empty())){ + std::pair ret + (slist_impl_.begin().operator->() + ,slist_impl_.last().operator->()); + slist_impl_.clear(); + return ret; + } + else { + return std::pair(); + } } }; diff --git a/include/boost/container/pmr/resource_adaptor.hpp b/include/boost/container/pmr/resource_adaptor.hpp index f5ce5c8..3340626 100644 --- a/include/boost/container/pmr/resource_adaptor.hpp +++ b/include/boost/container/pmr/resource_adaptor.hpp @@ -172,7 +172,7 @@ class resource_adaptor {} explicit resource_adaptor(BOOST_RV_REF(Allocator) a2) - : base_t(BOOST_MOVE_BASE(base_t, a2)) + : base_t(::boost::move(a2)) {} resource_adaptor& operator=(BOOST_COPY_ASSIGN_REF(resource_adaptor) other) From 4fc4cfd8d8abaef04dfcce2e8e75e8d4fa586000 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Tue, 13 Nov 2018 23:17:51 +0100 Subject: [PATCH 12/12] Fix GitHub #89 ("Build fails on clang-5 with libstdc++7-dev (C++17 issue)") --- doc/container.qbk | 4 ++-- test/set_test.cpp | 24 ------------------------ 2 files changed, 2 insertions(+), 26 deletions(-) diff --git a/doc/container.qbk b/doc/container.qbk index 2061f27..6d065fb 100644 --- a/doc/container.qbk +++ b/doc/container.qbk @@ -1261,8 +1261,8 @@ use [*Boost.Container]? There are several reasons for that: * [@https://github.com/boostorg/container/pull/84 GitHub #84: ['"Allow vector to be assigned to itself"]]. * [@https://github.com/boostorg/container/pull/85 GitHub #85: ['"container: misc-typos"]]. * [@https://github.com/boostorg/container/pull/86 GitHub #86: ['"Add missing warning re-enabling include"]]. - * [@https://github.com/boostorg/container/issues/90 GitHub #90: ['"UBSAN failures detected in preflight CI PR "]]. - + * [@https://github.com/boostorg/container/issues/89 GitHub #89: ['"UBSAN failures detected in preflight CI PR"]]. + * [@https://github.com/boostorg/container/issues/90 GitHub #90: ['"Build fails on clang-5 with libstdc++7-dev (C++17 issue)"]]. [endsect] diff --git a/test/set_test.cpp b/test/set_test.cpp index 9164222..39ab1b7 100644 --- a/test/set_test.cpp +++ b/test/set_test.cpp @@ -605,30 +605,6 @@ int main () if(!node_type_test()) return 1; -#ifndef BOOST_CONTAINER_NO_CXX17_CTAD - //////////////////////////////////// - // Constructor Template Auto Deduction - //////////////////////////////////// - { - auto gold = std::set({ 1, 2, 3 }); - auto test = boost::container::set(gold.begin(), gold.end()); - if (test.size() != 3) - return 1; - test = boost::container::set(ordered_unique_range, gold.begin(), gold.end()); - if (test.size() != 3) - return 1; - } - { - auto gold = std::multiset({ 1, 2, 3 }); - auto test = boost::container::multiset(gold.begin(), gold.end()); - if (test.size() != 3) - return 1; - test = boost::container::multiset(ordered_range, gold.begin(), gold.end()); - if (test.size() != 3) - return 1; - } -#endif - return 0; }