From ccdb1d856e621bba56c22e6730f42e79d5535d38 Mon Sep 17 00:00:00 2001 From: Liwei Ge Date: Fri, 1 Jan 2021 22:04:30 +0800 Subject: [PATCH] [build][c++] backport patches to fit with C++20 until upstream chase up Signed-off-by: Liwei Ge Signed-off-by: weitao zhou --- ...:allocate-with-std::allocator_traits.patch | 30 + ...ce-std::allocate-deprecated-in-C++17.patch | 599 ++++++ 1003-Implement-empty_value.patch | 295 +++ ...-empty_value-trivial-if-T-is-trivial.patch | 57 + 1005-Add-documentation-for-empty_value.patch | 175 ++ ...-the-empty_value-template-parameters.patch | 22 + 1007-Improve-C++11-allocator-support.patch | 572 ++++++ ...rebind-instead-of-A::template-rebind.patch | 33 + ...Implement-allocator-access-utilities.patch | 1661 +++++++++++++++++ boost.spec | 39 +- 10 files changed, 3482 insertions(+), 1 deletion(-) create mode 100644 1001-Replace-std::allocate-with-std::allocator_traits.patch create mode 100644 1002-Replace-std::allocate-deprecated-in-C++17.patch create mode 100644 1003-Implement-empty_value.patch create mode 100644 1004-Make-empty_value-trivial-if-T-is-trivial.patch create mode 100644 1005-Add-documentation-for-empty_value.patch create mode 100644 1006-Name-the-empty_value-template-parameters.patch create mode 100644 1007-Improve-C++11-allocator-support.patch create mode 100644 1008-Use-boost::allocator_rebind-instead-of-A::template-rebind.patch create mode 100644 1009-Implement-allocator-access-utilities.patch diff --git a/1001-Replace-std::allocate-with-std::allocator_traits.patch b/1001-Replace-std::allocate-with-std::allocator_traits.patch new file mode 100644 index 0000000..c51829d --- /dev/null +++ b/1001-Replace-std::allocate-with-std::allocator_traits.patch @@ -0,0 +1,30 @@ +From 1631ba81345c9e6bff270ab421f3a9a8690f47ae Mon Sep 17 00:00:00 2001 +From: Daniela Engert +Date: Sat, 30 Dec 2017 18:15:56 +0100 +Subject: [PATCH] Most members of std::allocate are deprecated in C++17 + +Replace them by their cousins from std::allocator_traits. + +Signed-off-by: Daniela Engert +--- + include/boost/detail/allocator_utilities.hpp | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/include/boost/detail/allocator_utilities.hpp b/include/boost/detail/allocator_utilities.hpp +index ed3de846..868d7121 100644 +--- a/include/boost/detail/allocator_utilities.hpp ++++ b/include/boost/detail/allocator_utilities.hpp +@@ -121,8 +121,13 @@ struct rebinder + template + struct result + { ++#ifdef BOOST_NO_CXX11_ALLOCATOR + typedef typename Allocator::BOOST_NESTED_TEMPLATE + rebind::other other; ++#else ++ typedef typename std::allocator_traits::BOOST_NESTED_TEMPLATE ++ rebind_alloc other; ++#endif + }; + }; + diff --git a/1002-Replace-std::allocate-deprecated-in-C++17.patch b/1002-Replace-std::allocate-deprecated-in-C++17.patch new file mode 100644 index 0000000..7a1d687 --- /dev/null +++ b/1002-Replace-std::allocate-deprecated-in-C++17.patch @@ -0,0 +1,599 @@ +From 58c42a46c1aedd2dc269f0775c36e867b98a988a Mon Sep 17 00:00:00 2001 +From: Daniela Engert +Date: Sun, 31 Dec 2017 09:50:23 +0100 +Subject: [PATCH] Most members of std::allocate are deprecated in C++17 + +Replace them by their cousins from std::allocator_traits. + +Signed-off-by: Daniela Engert +--- + .../boost/multi_index/detail/auto_space.hpp | 29 +++++++++++---- + include/boost/multi_index/detail/copy_map.hpp | 21 ++++++++++- + .../multi_index/detail/hash_index_node.hpp | 33 +++++++++++------ + .../multi_index/detail/ord_index_impl.hpp | 12 ++++++ + .../multi_index/detail/ord_index_node.hpp | 37 ++++++++++++------- + .../multi_index/detail/rnd_index_node.hpp | 24 ++++++++---- + .../detail/rnd_index_ptr_array.hpp | 10 ++++- + .../multi_index/detail/seq_index_node.hpp | 16 +++++--- + include/boost/multi_index/hashed_index.hpp | 9 +++++ + .../boost/multi_index/random_access_index.hpp | 12 ++++++ + include/boost/multi_index/sequenced_index.hpp | 12 ++++++ + include/boost/multi_index_container.hpp | 37 +++++++++++++++---- + 12 files changed, 198 insertions(+), 54 deletions(-) + +diff --git a/include/boost/multi_index/detail/auto_space.hpp b/include/boost/multi_index/detail/auto_space.hpp +index 9d78c3a3..28733c2f 100644 +--- a/include/boost/multi_index/detail/auto_space.hpp ++++ b/include/boost/multi_index/detail/auto_space.hpp +@@ -47,15 +47,31 @@ struct auto_space:private noncopyable + { + typedef typename boost::detail::allocator::rebind_to< + Allocator,T +- >::type::pointer pointer; ++ >::type allocator; ++#ifdef BOOST_NO_CXX11_ALLOCATOR ++ typedef typename allocator::pointer pointer; ++#else ++ typedef std::allocator_traits traits; ++ typedef typename traits::pointer pointer; ++#endif + + explicit auto_space(const Allocator& al=Allocator(),std::size_t n=1): +- al_(al),n_(n),data_(n_?al_.allocate(n_):pointer(0)) ++ al_(al),n_(n), ++#ifdef BOOST_NO_CXX11_ALLOCATOR ++ data_(n_?al_.allocate(n_):pointer(0)) ++#else ++ data_(n_?traits::allocate(al_,n_):pointer(0)) ++#endif + {} + + ~auto_space() + { +- if(n_)al_.deallocate(data_,n_); ++ if(n_) ++#ifdef BOOST_NO_CXX11_ALLOCATOR ++ al_.deallocate(data_,n_); ++#else ++ traits::deallocate(al_,data_,n_); ++#endif + } + + Allocator get_allocator()const{return al_;} +@@ -70,10 +86,9 @@ struct auto_space:private noncopyable + } + + private: +- typename boost::detail::allocator::rebind_to< +- Allocator,T>::type al_; +- std::size_t n_; +- pointer data_; ++ allocator al_; ++ std::size_t n_; ++ pointer data_; + }; + + template +diff --git a/include/boost/multi_index/detail/copy_map.hpp b/include/boost/multi_index/detail/copy_map.hpp +index 32c5dd99..2e460943 100644 +--- a/include/boost/multi_index/detail/copy_map.hpp ++++ b/include/boost/multi_index/detail/copy_map.hpp +@@ -22,6 +22,7 @@ + #include + #include + #include ++#include + + namespace boost{ + +@@ -84,7 +85,7 @@ class copy_map:private noncopyable + void clone(Node* node) + { + (spc.data()+n)->first=node; +- (spc.data()+n)->second=raw_ptr(al_.allocate(1)); ++ (spc.data()+n)->second=raw_ptr(allocate()); + BOOST_TRY{ + boost::detail::allocator::construct( + &(spc.data()+n)->second->value(),node->value()); +@@ -119,7 +120,12 @@ class copy_map:private noncopyable + typedef typename boost::detail::allocator::rebind_to< + Allocator,Node + >::type allocator_type; ++#ifdef BOOST_NO_CXX11_ALLOCATOR + typedef typename allocator_type::pointer allocator_pointer; ++#else ++ typedef std::allocator_traits allocator_traits; ++ typedef typename allocator_traits::pointer allocator_pointer; ++#endif + + allocator_type al_; + std::size_t size_; +@@ -129,9 +135,22 @@ class copy_map:private noncopyable + Node* header_cpy_; + bool released; + ++ allocator_pointer allocate() ++ { ++#ifdef BOOST_NO_CXX11_ALLOCATOR ++ return al_.allocate(1); ++#else ++ return allocator_traits::allocate(al_,1); ++#endif ++ } ++ + void deallocate(Node* node) + { ++#ifdef BOOST_NO_CXX11_ALLOCATOR + al_.deallocate(static_cast(node),1); ++#else ++ allocator_traits::deallocate(al_,static_cast(node),1); ++#endif + } + }; + +diff --git a/include/boost/multi_index/detail/hash_index_node.hpp b/include/boost/multi_index/detail/hash_index_node.hpp +index 7788e810..90a9a2d4 100644 +--- a/include/boost/multi_index/detail/hash_index_node.hpp ++++ b/include/boost/multi_index/detail/hash_index_node.hpp +@@ -17,6 +17,7 @@ + #include + #include + #include ++#include + + namespace boost{ + +@@ -99,24 +100,34 @@ struct hashed_index_node_impl; + template + struct hashed_index_base_node_impl + { +- typedef typename +- boost::detail::allocator::rebind_to< +- Allocator,hashed_index_base_node_impl +- >::type::pointer base_pointer; + typedef typename + boost::detail::allocator::rebind_to< + Allocator,hashed_index_base_node_impl +- >::type::const_pointer const_base_pointer; ++ >::type base_allocator; + typedef typename + boost::detail::allocator::rebind_to< + Allocator, + hashed_index_node_impl +- >::type::pointer pointer; +- typedef typename +- boost::detail::allocator::rebind_to< +- Allocator, +- hashed_index_node_impl +- >::type::const_pointer const_pointer; ++ >::type node_allocator; ++#ifdef BOOST_NO_CXX11_ALLOCATOR ++ typedef typename base_allocator::pointer base_pointer; ++ typedef typename base_allocator::const_pointer const_base_pointer; ++ typedef typename node_allocator::pointer pointer; ++ typedef typename node_allocator::const_pointer const_pointer; ++#else ++ typedef typename std::allocator_traits< ++ base_allocator ++ >::pointer base_pointer; ++ typedef typename std::allocator_traits< ++ base_allocator ++ >::const_pointer const_base_pointer; ++ typedef typename std::allocator_traits< ++ node_allocator ++ >::pointer pointer; ++ typedef typename std::allocator_traits< ++ node_allocator ++ >::const_pointer const_pointer; ++#endif + + pointer& prior(){return prior_;} + pointer prior()const{return prior_;} +diff --git a/include/boost/multi_index/detail/ord_index_impl.hpp b/include/boost/multi_index/detail/ord_index_impl.hpp +index d2ef7ee5..3800cfea 100644 +--- a/include/boost/multi_index/detail/ord_index_impl.hpp ++++ b/include/boost/multi_index/detail/ord_index_impl.hpp +@@ -69,6 +69,7 @@ + #include + #include + #include ++#include + + #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) + #include +@@ -162,8 +163,13 @@ class ordered_index_impl: + value_type,KeyFromValue,Compare> value_compare; + typedef tuple ctor_args; + typedef typename super::final_allocator_type allocator_type; ++#ifdef BOOST_NO_CXX11_ALLOCATOR + typedef typename allocator_type::reference reference; + typedef typename allocator_type::const_reference const_reference; ++#else ++ typedef value_type& reference; ++ typedef const value_type& const_reference; ++#endif + + #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE) + typedef safe_mode::safe_iterator< +@@ -177,8 +183,14 @@ class ordered_index_impl: + + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; ++#ifdef BOOST_NO_CXX11_ALLOCATOR + typedef typename allocator_type::pointer pointer; + typedef typename allocator_type::const_pointer const_pointer; ++#else ++ typedef std::allocator_traits allocator_traits; ++ typedef typename allocator_traits::pointer pointer; ++ typedef typename allocator_traits::const_pointer const_pointer; ++#endif + typedef typename + boost::reverse_iterator reverse_iterator; + typedef typename +diff --git a/include/boost/multi_index/detail/ord_index_node.hpp b/include/boost/multi_index/detail/ord_index_node.hpp +index e7af0377..42f03686 100644 +--- a/include/boost/multi_index/detail/ord_index_node.hpp ++++ b/include/boost/multi_index/detail/ord_index_node.hpp +@@ -42,6 +42,7 @@ + + #include /* keep it first to prevent nasty warns in MSVC */ + #include ++#include + #include + #include + +@@ -68,20 +69,33 @@ template + struct ordered_index_node_impl; /* fwd decl. */ + + template +-struct ordered_index_node_std_base ++struct ordered_index_node_traits + { + typedef typename + boost::detail::allocator::rebind_to< + Allocator, + ordered_index_node_impl +- >::type::pointer pointer; +- typedef typename +- boost::detail::allocator::rebind_to< +- Allocator, +- ordered_index_node_impl +- >::type::const_pointer const_pointer; +- typedef ordered_index_color& color_ref; +- typedef pointer& parent_ref; ++ >::type allocator; ++#ifdef BOOST_NO_CXX11_ALLOCATOR ++ typedef typename allocator::pointer pointer; ++ typedef typename allocator::const_pointer const_pointer; ++#else ++ typedef std::allocator_traits allocator_traits; ++ typedef typename allocator_traits::pointer pointer; ++ typedef typename allocator_traits::const_pointer const_pointer; ++#endif ++}; ++ ++template ++struct ordered_index_node_std_base ++{ ++ typedef ordered_index_node_traits< ++ AugmentPolicy,Allocator> node_traits; ++ typedef typename node_traits::allocator node_allocator; ++ typedef typename node_traits::pointer pointer; ++ typedef typename node_traits::const_pointer const_pointer; ++ typedef ordered_index_color& color_ref; ++ typedef pointer& parent_ref; + + ordered_index_color& color(){return color_;} + ordered_index_color color()const{return color_;} +@@ -217,10 +231,7 @@ struct ordered_index_node_impl_base: + ordered_index_node_compressed_base + >::value%2)|| + !(is_same< +- typename boost::detail::allocator::rebind_to< +- Allocator, +- ordered_index_node_impl +- >::type::pointer, ++ typename ordered_index_node_traits::pointer, + ordered_index_node_impl*>::value), + ordered_index_node_std_base, + ordered_index_node_compressed_base +diff --git a/include/boost/multi_index/detail/rnd_index_node.hpp b/include/boost/multi_index/detail/rnd_index_node.hpp +index ad61ea25..4faef650 100644 +--- a/include/boost/multi_index/detail/rnd_index_node.hpp ++++ b/include/boost/multi_index/detail/rnd_index_node.hpp +@@ -20,6 +20,7 @@ + #include + #include + #include ++#include + + namespace boost{ + +@@ -33,16 +34,25 @@ struct random_access_index_node_impl + typedef typename + boost::detail::allocator::rebind_to< + Allocator,random_access_index_node_impl +- >::type::pointer pointer; +- typedef typename +- boost::detail::allocator::rebind_to< +- Allocator,random_access_index_node_impl +- >::type::const_pointer const_pointer; ++ >::type node_allocator; ++#ifdef BOOST_NO_CXX11_ALLOCATOR ++ typedef typename node_allocator::pointer pointer; ++ typedef typename node_allocator::const_pointer const_pointer; ++#else ++ typedef std::allocator_traits node_traits; ++ typedef typename node_traits::pointer pointer; ++ typedef typename node_traits::const_pointer const_pointer; ++#endif + typedef typename + boost::detail::allocator::rebind_to< + Allocator,pointer +- >::type::pointer ptr_pointer; +- ++ >::type ptr_allocator; ++#ifdef BOOST_NO_CXX11_ALLOCATOR ++ typedef typename ptr_allocator::pointer ptr_pointer; ++#else ++ typedef std::allocator_traits ptr_traits; ++ typedef typename ptr_traits::pointer ptr_pointer; ++#endif + ptr_pointer& up(){return up_;} + ptr_pointer up()const{return up_;} + +diff --git a/include/boost/multi_index/detail/rnd_index_ptr_array.hpp b/include/boost/multi_index/detail/rnd_index_ptr_array.hpp +index bae1c851..483a4962 100644 +--- a/include/boost/multi_index/detail/rnd_index_ptr_array.hpp ++++ b/include/boost/multi_index/detail/rnd_index_ptr_array.hpp +@@ -20,6 +20,7 @@ + #include + #include + #include ++#include + + namespace boost{ + +@@ -43,7 +44,14 @@ class random_access_index_ptr_array:private noncopyable + typedef typename node_impl_type::pointer value_type; + typedef typename boost::detail::allocator::rebind_to< + Allocator,value_type +- >::type::pointer pointer; ++ >::type value_allocator; ++#ifdef BOOST_NO_CXX11_ALLOCATOR ++ typedef typename value_allocator::pointer pointer; ++#else ++ typedef typename std::allocator_traits< ++ value_allocator ++ >::pointer pointer; ++#endif + + random_access_index_ptr_array( + const Allocator& al,value_type end_,std::size_t sz): +diff --git a/include/boost/multi_index/detail/seq_index_node.hpp b/include/boost/multi_index/detail/seq_index_node.hpp +index 85b345af..692c2b57 100644 +--- a/include/boost/multi_index/detail/seq_index_node.hpp ++++ b/include/boost/multi_index/detail/seq_index_node.hpp +@@ -15,6 +15,7 @@ + + #include /* keep it first to prevent nasty warns in MSVC */ + #include ++#include + #include + #include + +@@ -32,12 +33,15 @@ struct sequenced_index_node_impl + typedef typename + boost::detail::allocator::rebind_to< + Allocator,sequenced_index_node_impl +- >::type::pointer pointer; +- typedef typename +- boost::detail::allocator::rebind_to< +- Allocator,sequenced_index_node_impl +- >::type::const_pointer const_pointer; +- ++ >::type node_allocator; ++#ifdef BOOST_NO_CXX11_ALLOCATOR ++ typedef typename node_allocator::pointer pointer; ++ typedef typename node_allocator::const_pointer const_pointer; ++#else ++ typedef std::allocator_traits allocator_traits; ++ typedef typename allocator_traits::pointer pointer; ++ typedef typename allocator_traits::const_pointer const_pointer; ++#endif + pointer& prior(){return prior_;} + pointer prior()const{return prior_;} + pointer& next(){return next_;} +diff --git a/include/boost/multi_index/hashed_index.hpp b/include/boost/multi_index/hashed_index.hpp +index a6ae2a0e..cbd5fb66 100644 +--- a/include/boost/multi_index/hashed_index.hpp ++++ b/include/boost/multi_index/hashed_index.hpp +@@ -45,6 +45,7 @@ + #include + #include + #include ++#include + + #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) + #include +@@ -127,10 +128,18 @@ class hashed_index: + typedef tuple ctor_args; + typedef typename super::final_allocator_type allocator_type; ++#ifdef BOOST_NO_CXX11_ALLOCATOR + typedef typename allocator_type::pointer pointer; + typedef typename allocator_type::const_pointer const_pointer; + typedef typename allocator_type::reference reference; + typedef typename allocator_type::const_reference const_reference; ++#else ++ typedef std::allocator_traits allocator_traits; ++ typedef typename allocator_traits::pointer pointer; ++ typedef typename allocator_traits::const_pointer const_pointer; ++ typedef value_type& reference; ++ typedef const value_type& const_reference; ++#endif + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + +diff --git a/include/boost/multi_index/random_access_index.hpp b/include/boost/multi_index/random_access_index.hpp +index a0c9ba9c..eeebdd83 100644 +--- a/include/boost/multi_index/random_access_index.hpp ++++ b/include/boost/multi_index/random_access_index.hpp +@@ -45,6 +45,7 @@ + #include + #include + #include ++#include + + #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) + #include +@@ -114,8 +115,13 @@ class random_access_index: + typedef typename node_type::value_type value_type; + typedef tuples::null_type ctor_args; + typedef typename super::final_allocator_type allocator_type; ++#ifdef BOOST_NO_CXX11_ALLOCATOR + typedef typename allocator_type::reference reference; + typedef typename allocator_type::const_reference const_reference; ++#else ++ typedef value_type& reference; ++ typedef const value_type& const_reference; ++#endif + + #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE) + typedef safe_mode::safe_iterator< +@@ -129,8 +135,14 @@ class random_access_index: + + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; ++#ifdef BOOST_NO_CXX11_ALLOCATOR + typedef typename allocator_type::pointer pointer; + typedef typename allocator_type::const_pointer const_pointer; ++#else ++ typedef std::allocator_traits allocator_traits; ++ typedef typename allocator_traits::pointer pointer; ++ typedef typename allocator_traits::const_pointer const_pointer; ++#endif + typedef typename + boost::reverse_iterator reverse_iterator; + typedef typename +diff --git a/include/boost/multi_index/sequenced_index.hpp b/include/boost/multi_index/sequenced_index.hpp +index 72ee7bcd..895b4c30 100644 +--- a/include/boost/multi_index/sequenced_index.hpp ++++ b/include/boost/multi_index/sequenced_index.hpp +@@ -42,6 +42,7 @@ + #include + #include + #include ++#include + + #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) + #include +@@ -106,8 +107,13 @@ class sequenced_index: + typedef typename node_type::value_type value_type; + typedef tuples::null_type ctor_args; + typedef typename super::final_allocator_type allocator_type; ++#ifdef BOOST_NO_CXX11_ALLOCATOR + typedef typename allocator_type::reference reference; + typedef typename allocator_type::const_reference const_reference; ++#else ++ typedef value_type& reference; ++ typedef const value_type& const_reference; ++#endif + + #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE) + typedef safe_mode::safe_iterator< +@@ -121,8 +127,14 @@ class sequenced_index: + + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; ++#ifdef BOOST_NO_CXX11_ALLOCATOR + typedef typename allocator_type::pointer pointer; + typedef typename allocator_type::const_pointer const_pointer; ++#else ++ typedef std::allocator_traits allocator_traits; ++ typedef typename allocator_traits::pointer pointer; ++ typedef typename allocator_traits::const_pointer const_pointer; ++#endif + typedef typename + boost::reverse_iterator reverse_iterator; + typedef typename +diff --git a/include/boost/multi_index_container.hpp b/include/boost/multi_index_container.hpp +index f1f9656a..332e958b 100644 +--- a/include/boost/multi_index_container.hpp ++++ b/include/boost/multi_index_container.hpp +@@ -17,6 +17,7 @@ + + #include /* keep it first to prevent nasty warns in MSVC */ + #include ++#include + #include + #include + #include +@@ -90,11 +91,19 @@ class multi_index_container: + Value,IndexSpecifierList,Allocator>::type + >::type>, + BOOST_MULTI_INDEX_PRIVATE_IF_MEMBER_TEMPLATE_FRIENDS detail::header_holder< +- typename boost::detail::allocator::rebind_to< +- Allocator, +- typename detail::multi_index_node_type< +- Value,IndexSpecifierList,Allocator>::type +- >::type::pointer, ++#ifndef BOOST_NO_CXX11_ALLOCATOR ++ typename std::allocator_traits< ++#endif ++ typename boost::detail::allocator::rebind_to< ++ Allocator, ++ typename detail::multi_index_node_type< ++ Value,IndexSpecifierList,Allocator>::type ++ >::type ++#ifdef BOOST_NO_CXX11_ALLOCATOR ++ ::pointer, ++#else ++ >::pointer, ++#endif + multi_index_container >, + public detail::multi_index_base_type< + Value,IndexSpecifierList,Allocator>::type +@@ -125,13 +134,18 @@ class multi_index_container: + Allocator, + typename super::node_type + >::type node_allocator; ++#ifdef BOOST_NO_CXX11_ALLOCATOR ++ typedef typename node_allocator::pointer node_pointer; ++#else ++ typedef std::allocator_traits node_allocator_traits; ++ typedef typename node_allocator_traits::pointer node_pointer; ++#endif + typedef ::boost::base_from_member< + node_allocator> bfm_allocator; + typedef detail::header_holder< +- typename node_allocator::pointer, ++ node_pointer, + multi_index_container> bfm_header; + +- + public: + /* All types are inherited from super, a few are explicitly + * brought forward here to save us some typename's. +@@ -528,13 +542,20 @@ class multi_index_container: + + node_type* allocate_node() + { ++#ifdef BOOST_NO_CXX11_ALLOCATOR + return &*bfm_allocator::member.allocate(1); ++#else ++ return &*node_allocator_traits::allocate(bfm_allocator::member,1); ++#endif + } + + void deallocate_node(node_type* x) + { +- typedef typename node_allocator::pointer node_pointer; ++#ifdef BOOST_NO_CXX11_ALLOCATOR + bfm_allocator::member.deallocate(static_cast(x),1); ++#else ++ node_allocator_traits::deallocate(bfm_allocator::member,static_cast(x),1); ++#endif + } + + bool empty_()const diff --git a/1003-Implement-empty_value.patch b/1003-Implement-empty_value.patch new file mode 100644 index 0000000..52335e4 --- /dev/null +++ b/1003-Implement-empty_value.patch @@ -0,0 +1,295 @@ +From f504872d89d2c17de8874fde92b457c9b3274f96 Mon Sep 17 00:00:00 2001 +From: Glen Fernandes +Date: Wed, 22 Aug 2018 11:09:31 -0400 +Subject: [PATCH] Implement empty_value + +--- + include/boost/core/empty_value.hpp | 113 +++++++++++++++++++++++++++++ + test/Jamfile.v2 | 3 + + test/empty_value_size_test.cpp | 60 +++++++++++++++ + test/empty_value_test.cpp | 76 +++++++++++++++++++ + 4 files changed, 252 insertions(+) + create mode 100644 include/boost/core/empty_value.hpp + create mode 100644 test/empty_value_size_test.cpp + create mode 100644 test/empty_value_test.cpp + +diff --git a/include/boost/core/empty_value.hpp b/include/boost/core/empty_value.hpp +new file mode 100644 +index 0000000..8853588 +--- /dev/null ++++ b/include/boost/core/empty_value.hpp +@@ -0,0 +1,113 @@ ++/* ++Copyright 2018 Glen Joseph Fernandes ++(glenjofe@gmail.com) ++ ++Distributed under the Boost Software License, Version 1.0. ++(http://www.boost.org/LICENSE_1_0.txt) ++*/ ++#ifndef BOOST_CORE_EMPTY_VALUE_HPP ++#define BOOST_CORE_EMPTY_VALUE_HPP ++ ++#include ++#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) ++#include ++#endif ++ ++#if defined(BOOST_GCC_VERSION) && (BOOST_GCC_VERSION >= 40700) ++#define BOOST_DETAIL_EMPTY_VALUE_BASE ++#elif defined(BOOST_INTEL) && defined(_MSC_VER) && (_MSC_VER >= 1800) ++#define BOOST_DETAIL_EMPTY_VALUE_BASE ++#elif defined(BOOST_MSVC) && (BOOST_MSVC >= 1800) ++#define BOOST_DETAIL_EMPTY_VALUE_BASE ++#elif defined(BOOST_CLANG) && !defined(__CUDACC__) ++#if __has_feature(is_empty) && __has_feature(is_final) ++#define BOOST_DETAIL_EMPTY_VALUE_BASE ++#endif ++#endif ++ ++namespace boost { ++ ++template ++struct use_empty_value_base { ++ enum { ++#if defined(BOOST_DETAIL_EMPTY_VALUE_BASE) ++ value = __is_empty(T) && !__is_final(T) ++#else ++ value = false ++#endif ++ }; ++}; ++ ++struct empty_init_t { }; ++ ++template::value> ++class empty_value { ++public: ++ empty_value() ++ : value_() { } ++ ++#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) ++#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) ++ template ++ empty_value(empty_init_t, Args&&... args) ++ : value_(std::forward(args)...) { } ++#else ++ template ++ empty_value(empty_init_t, U&& value) ++ : value_(std::forward(value)) { } ++#endif ++#else ++ template ++ empty_value(empty_init_t, const U& value) ++ : value_(value) { } ++#endif ++ ++ const T& get() const BOOST_NOEXCEPT { ++ return value_; ++ } ++ ++ T& get() BOOST_NOEXCEPT { ++ return value_; ++ } ++ ++private: ++ T value_; ++}; ++ ++#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) ++template ++class empty_value ++ : T { ++public: ++ empty_value() ++ : T() { } ++ ++#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) ++#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) ++ template ++ empty_value(empty_init_t, Args&&... args) ++ : T(std::forward(args)...) { } ++#else ++ template ++ empty_value(empty_init_t, U&& value) ++ : T(std::forward(value)) { } ++#endif ++#else ++ template ++ empty_value(empty_init_t, const U& value) ++ : T(value) { } ++#endif ++ ++ const T& get() const BOOST_NOEXCEPT { ++ return *this; ++ } ++ ++ T& get() BOOST_NOEXCEPT { ++ return *this; ++ } ++}; ++#endif ++ ++} /* boost */ ++ ++#endif +diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 +index 320fca9..284b4c1 100644 +--- a/boost/libs/core/test/Jamfile.v2 ++++ b/boost/libs/core/test/Jamfile.v2 +@@ -123,5 +123,8 @@ run to_address_test.cpp ; + run pointer_traits_pointer_to_test.cpp ; + run to_address_test.cpp ; + ++run empty_value_test.cpp ; ++run empty_value_size_test.cpp ; ++ + use-project /boost/core/swap : ./swap ; + build-project ./swap ; +diff --git a/test/empty_value_size_test.cpp b/test/empty_value_size_test.cpp +new file mode 100644 +index 0000000..f0ed675 +--- /dev/null ++++ b/boost/libs/core/test/empty_value_size_test.cpp +@@ -0,0 +1,60 @@ ++/* ++Copyright 2018 Glen Joseph Fernandes ++(glenjofe@gmail.com) ++ ++Distributed under the Boost Software License, Version 1.0. ++(http://www.boost.org/LICENSE_1_0.txt) ++*/ ++#include ++#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) ++#include ++#include ++ ++struct T1 { }; ++ ++struct S1 ++ : boost::empty_value { }; ++ ++struct T2 { ++ int value; ++}; ++ ++struct S2 ++ : boost::empty_value ++ , boost::empty_value { }; ++ ++struct S3 ++ : boost::empty_value ++ , boost::empty_value { }; ++ ++struct T3 { }; ++ ++struct S4 ++ : boost::empty_value ++ , boost::empty_value { }; ++ ++struct S5 ++ : boost::empty_value ++ , boost::empty_value { }; ++ ++struct S6 ++ : boost::empty_value ++ , boost::empty_value ++ , boost::empty_value { }; ++ ++int main() ++{ ++ BOOST_TEST(sizeof(S1) == sizeof(T1)); ++ BOOST_TEST(sizeof(S2) == sizeof(T2)); ++ BOOST_TEST(sizeof(S3) > sizeof(T2)); ++ BOOST_TEST(sizeof(S4) == sizeof(T1)); ++ BOOST_TEST(sizeof(S5) > sizeof(T1)); ++ BOOST_TEST(sizeof(S6) == sizeof(T2)); ++ return boost::report_errors(); ++} ++#else ++int main() ++{ ++ return 0; ++} ++#endif +diff --git a/test/empty_value_test.cpp b/test/empty_value_test.cpp +new file mode 100644 +index 0000000..d7261b6 +--- /dev/null ++++ b/boost/libs/core/test/empty_value_test.cpp +@@ -0,0 +1,76 @@ ++/* ++Copyright 2018 Glen Joseph Fernandes ++(glenjofe@gmail.com) ++ ++Distributed under the Boost Software License, Version 1.0. ++(http://www.boost.org/LICENSE_1_0.txt) ++*/ ++#include ++#include ++ ++struct empty { ++ operator bool() const { ++ return false; ++ } ++ operator bool() { ++ return true; ++ } ++}; ++ ++class type { ++public: ++ type() ++ : value_(false) { } ++ explicit type(bool value) ++ : value_(value) { } ++ operator bool() const { ++ return value_; ++ } ++private: ++ bool value_; ++}; ++ ++void test_bool() ++{ ++ const boost::empty_value v1(boost::empty_init_t(), true); ++ BOOST_TEST(v1.get()); ++ boost::empty_value v2; ++ BOOST_TEST(!v2.get()); ++ v2 = v1; ++ BOOST_TEST(v2.get()); ++ v2.get() = false; ++ BOOST_TEST(!v2.get()); ++} ++ ++void test_empty() ++{ ++ empty e; ++ const boost::empty_value v1(boost::empty_init_t(), e); ++ BOOST_TEST(!v1.get()); ++ boost::empty_value v2; ++ BOOST_TEST(v2.get()); ++ v2 = v1; ++ BOOST_TEST(v2.get()); ++ v2.get() = empty(); ++ BOOST_TEST(v2.get()); ++} ++ ++void test_type() ++{ ++ const boost::empty_value v1(boost::empty_init_t(), true); ++ BOOST_TEST(v1.get()); ++ boost::empty_value v2; ++ BOOST_TEST(!v2.get()); ++ v2 = v1; ++ BOOST_TEST(v2.get()); ++ v2.get() = type(); ++ BOOST_TEST(!v2.get()); ++} ++ ++int main() ++{ ++ test_bool(); ++ test_empty(); ++ test_type(); ++ return boost::report_errors(); ++} diff --git a/1004-Make-empty_value-trivial-if-T-is-trivial.patch b/1004-Make-empty_value-trivial-if-T-is-trivial.patch new file mode 100644 index 0000000..f691760 --- /dev/null +++ b/1004-Make-empty_value-trivial-if-T-is-trivial.patch @@ -0,0 +1,57 @@ +From 2eaba7d6d1c359556308d8805e27495509e2854a Mon Sep 17 00:00:00 2001 +From: Glen Fernandes +Date: Sun, 26 Aug 2018 02:08:51 -0400 +Subject: [PATCH] Make empty_value trivial if T is trivial + +--- + include/boost/core/empty_value.hpp | 16 ++++++++++++++-- + test/empty_value_test.cpp | 2 +- + 2 files changed, 15 insertions(+), 3 deletions(-) + +diff --git a/include/boost/core/empty_value.hpp b/include/boost/core/empty_value.hpp +index 8853588..b67d42c 100644 +--- a/include/boost/core/empty_value.hpp ++++ b/include/boost/core/empty_value.hpp +@@ -43,7 +43,13 @@ struct empty_init_t { }; + template::value> + class empty_value { + public: +- empty_value() ++#if !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) ++ empty_value() = default; ++#else ++ empty_value() { } ++#endif ++ ++ empty_value(empty_init_t) + : value_() { } + + #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) +@@ -79,7 +85,13 @@ template + class empty_value + : T { + public: +- empty_value() ++#if !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) ++ empty_value() = default; ++#else ++ empty_value() { } ++#endif ++ ++ empty_value(empty_init_t) + : T() { } + + #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) +diff --git a/test/empty_value_test.cpp b/test/empty_value_test.cpp +index d7261b6..7c90594 100644 +--- a/test/empty_value_test.cpp ++++ b/test/empty_value_test.cpp +@@ -34,7 +34,7 @@ void test_bool() + { + const boost::empty_value v1(boost::empty_init_t(), true); + BOOST_TEST(v1.get()); +- boost::empty_value v2; ++ boost::empty_value v2 = boost::empty_init_t(); + BOOST_TEST(!v2.get()); + v2 = v1; + BOOST_TEST(v2.get()); diff --git a/1005-Add-documentation-for-empty_value.patch b/1005-Add-documentation-for-empty_value.patch new file mode 100644 index 0000000..e3cda45 --- /dev/null +++ b/1005-Add-documentation-for-empty_value.patch @@ -0,0 +1,175 @@ +From edcd9e2cf55c5b1289fccfc183be5804b7f95e72 Mon Sep 17 00:00:00 2001 +From: Glen Fernandes +Date: Sun, 26 Aug 2018 10:07:19 -0400 +Subject: [PATCH] Add documentation for empty_value + +--- + doc/core.qbk | 1 + + doc/empty_value.qbk | 123 +++++++++++++++++++++++++++++ + include/boost/core/empty_value.hpp | 4 +- + 3 files changed, 126 insertions(+), 2 deletions(-) + create mode 100644 doc/empty_value.qbk + +diff --git a/doc/core.qbk b/doc/core.qbk +index 0eaaf67..3583bc6 100644 +--- a/boost/libs/core/doc/core.qbk ++++ b/boost/libs/core/doc/core.qbk +@@ -41,6 +41,7 @@ criteria for inclusion is that the utility component be: + [include addressof.qbk] + [include checked_delete.qbk] + [include demangle.qbk] ++[include empty_value.qbk] + [include enable_if.qbk] + [include explicit_operator_bool.qbk] + [include ignore_unused.qbk] +diff --git a/doc/empty_value.qbk b/doc/empty_value.qbk +new file mode 100644 +index 0000000..cb6cb12 +--- /dev/null ++++ b/boost/libs/core/doc/empty_value.qbk +@@ -0,0 +1,123 @@ ++[/ ++Copyright 2018 Glen Joseph Fernandes ++(glenjofe@gmail.com) ++ ++Distributed under the Boost Software License, Version 1.0. ++(http://www.boost.org/LICENSE_1_0.txt) ++] ++ ++[section:empty_value empty_value] ++ ++[simplesect Authors] ++ ++* Glen Fernandes ++ ++[endsimplesect] ++ ++[section Overview] ++ ++The header provides the class template ++`boost::empty_value` for library authors to conveniently leverage the Empty ++Base Optimization to store objects of potentially empty types. ++ ++[endsect] ++ ++[section Examples] ++ ++The following example shows `boost::empty_value` used to create a type that ++stores a pointer, comparer, and allocator, where the comparer and allocator ++could be empty types. ++ ++``` ++template ++class storage ++ : empty_value ++ , empty_value { ++public: ++ storage() ++ : empty_value(empty_init_t()) ++ , empty_value(empty_init_t()) ++ , ptr_() { } ++ ++ storage(const Compare& c, const Allocator& a) ++ : empty_value(empty_init_t(), c) ++ , empty_value(empty_init_t(), a) ++ , ptr_() { } ++ ++ const Ptr& pointer() const ++ { return ptr_; } ++ ++ Ptr& pointer() ++ { return ptr_; } ++ ++ const Compare& compare() const ++ { return empty_value::get(); } ++ ++ Compare& compare() ++ { return empty_value::get(); } ++ ++ const Allocator& allocator() const ++ { return empty_value::get(); } ++ ++ Allocator& allocator() ++ { return empty_value::get(); } ++ ++private: ++ Ptr ptr_; ++}; ++``` ++ ++[endsect] ++ ++[section Reference] ++ ++``` ++namespace boost { ++ ++struct empty_init_t { }; ++ ++template ++class empty_value { ++public: ++ empty_value() = default; ++ ++ template ++ explicit empty_value(empty_init_t, Args&&... args); ++ ++ const T& get() const; ++ ++ T& get(); ++}; ++ ++} /* boost */ ++``` ++ ++[section Template parameters] ++ ++[variablelist ++[[`T`][The type of value to store]] ++[[`Index`][Optional: Specify to create a distinct base type]] ++[[`Empty`][Optional: Specify to force inheritance from type]]] ++ ++[endsect] ++ ++[section Constructors] ++ ++[variablelist ++[[`empty_value() = default;`][Default initialize the value]] ++[[`template empty_value(empty_init_t, Args&&... args);`] ++[Initialize the value with `std::forward(args)...`]]] ++ ++[endsect] ++ ++[section Member functions] ++ ++[variablelist ++[[`const T& get() const;`][Returns the value]] ++[[`T& get();`][Returns the value]]] ++ ++[endsect] ++ ++[endsect] ++ ++[endsect] +diff --git a/include/boost/core/empty_value.hpp b/include/boost/core/empty_value.hpp +index b67d42c..a10e1bf 100644 +--- a/include/boost/core/empty_value.hpp ++++ b/include/boost/core/empty_value.hpp +@@ -55,7 +55,7 @@ class empty_value { + #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + template +- empty_value(empty_init_t, Args&&... args) ++ explicit empty_value(empty_init_t, Args&&... args) + : value_(std::forward(args)...) { } + #else + template +@@ -97,7 +97,7 @@ class empty_value + #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + template +- empty_value(empty_init_t, Args&&... args) ++ explicit empty_value(empty_init_t, Args&&... args) + : T(std::forward(args)...) { } + #else + template diff --git a/1006-Name-the-empty_value-template-parameters.patch b/1006-Name-the-empty_value-template-parameters.patch new file mode 100644 index 0000000..ac412d9 --- /dev/null +++ b/1006-Name-the-empty_value-template-parameters.patch @@ -0,0 +1,22 @@ +From 2d99acd7ec8659c65454bd6167aac3e361cef983 Mon Sep 17 00:00:00 2001 +From: Glen Fernandes +Date: Mon, 27 Aug 2018 22:45:54 -0400 +Subject: [PATCH] Name the empty_value template parameters + +--- + include/boost/core/empty_value.hpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/include/boost/core/empty_value.hpp b/include/boost/core/empty_value.hpp +index a10e1bf..0902e00 100644 +--- a/include/boost/core/empty_value.hpp ++++ b/include/boost/core/empty_value.hpp +@@ -40,7 +40,7 @@ struct use_empty_value_base { + + struct empty_init_t { }; + +-template::value> ++template::value> + class empty_value { + public: + #if !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) diff --git a/1007-Improve-C++11-allocator-support.patch b/1007-Improve-C++11-allocator-support.patch new file mode 100644 index 0000000..94e860e --- /dev/null +++ b/1007-Improve-C++11-allocator-support.patch @@ -0,0 +1,572 @@ +From e9229c8bf46aaee3a7cae990a1c60a574cda2793 Mon Sep 17 00:00:00 2001 +From: Glen Fernandes +Date: Wed, 5 Sep 2018 11:05:58 -0400 +Subject: [PATCH] Improve C++11 allocator support + +* Use the empty base optimization for storing the allocator +* Support C++11 minimal allocators +* Support C++11 stateful allocators +* Support C++11 allocator construct and destroy +--- + doc/user.html | 5 + + doc/xml/multi_array.xml | 40 ++++-- + include/boost/multi_array.hpp | 166 ++++++++++++++++------- + include/boost/multi_array/allocators.hpp | 72 ++++++++++ + 4 files changed, 218 insertions(+), 65 deletions(-) + create mode 100644 include/boost/multi_array/allocators.hpp + +diff --git a/doc/user.html b/doc/user.html +index 5721128b..57d73a30 100644 +--- a/boost/libs/multi_array/doc/user.html ++++ b/boost/libs/multi_array/doc/user.html +@@ -661,6 +661,11 @@

Credits

+
  • Beman Dawes + helped immensely with porting the library to Microsoft Windows + compilers. ++ ++
  • Glen Fernandes ++ implemented support for the C++11 allocator model, including ++ support for stateful allocators, minimal allocators, and ++ optimized storage for stateless allocators. + + +
    +diff --git a/doc/xml/multi_array.xml b/doc/xml/multi_array.xml +index db42882c..01e2d8d6 100644 +--- a/boost/libs/multi_array/doc/xml/multi_array.xml ++++ b/boost/libs/multi_array/doc/xml/multi_array.xml +@@ -65,7 +65,7 @@ public: + + // constructors and destructors + +- multi_array(); ++ multi_array(const Allocator& alloc = Allocator()); + + template + explicit multi_array(const ExtentList& sizes, +@@ -75,13 +75,19 @@ public: + const storage_order_type& store = c_storage_order(), + const Allocator& alloc = Allocator()); + multi_array(const multi_array& x); +- multi_array(const const_multi_array_ref& x); +- multi_array(const const_subarray::type& x); +- multi_array(const const_array_view::type& x); +- +- multi_array(const multi_array_ref& x); +- multi_array(const subarray::type& x); +- multi_array(const array_view::type& x); ++ multi_array(const const_multi_array_ref& x, ++ const Allocator& alloc = Allocator()); ++ multi_array(const const_subarray::type& x, ++ const Allocator& alloc = Allocator()); ++ multi_array(const const_array_view::type& x, ++ const Allocator& alloc = Allocator()); ++ ++ multi_array(const multi_array_ref& x, ++ const Allocator& alloc = Allocator()); ++ multi_array(const subarray::type& x, ++ const Allocator& alloc = Allocator()); ++ multi_array(const array_view::type& x, ++ const Allocator& alloc = Allocator()); + + ~multi_array(); + +@@ -207,12 +213,18 @@ elements. + + + & x); +-multi_array(const const_subarray::type& x); +-multi_array(const const_array_view::type& x); +-multi_array(const multi_array_ref& x); +-multi_array(const subarray::type& x); +-multi_array(const array_view::type& x);]]> ++multi_array(const const_multi_array_ref& x, ++ const Allocator& alloc = Allocator()); ++multi_array(const const_subarray::type& x, ++ const Allocator& alloc = Allocator()); ++multi_array(const const_array_view::type& x, ++ const Allocator& alloc = Allocator()); ++multi_array(const multi_array_ref& x, ++ const Allocator& alloc = Allocator()); ++multi_array(const subarray::type& x, ++ const Allocator& alloc = Allocator()); ++multi_array(const array_view::type& x, ++ const Allocator& alloc = Allocator());]]> + + + These constructors all constructs a multi_array and +diff --git a/include/boost/multi_array.hpp b/include/boost/multi_array.hpp +index a134abb5..46979ac7 100644 +--- a/include/boost/multi_array.hpp ++++ b/include/boost/multi_array.hpp +@@ -1,5 +1,8 @@ + // Copyright 2002 The Trustees of Indiana University. + ++// Copyright 2018 Glen Joseph Fernandes ++// (glenjofe@gmail.com) ++ + // Use, modification and distribution is subject to the Boost Software + // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at + // http://www.boost.org/LICENSE_1_0.txt) +@@ -30,6 +33,8 @@ + #include "boost/multi_array/subarray.hpp" + #include "boost/multi_array/multi_array_ref.hpp" + #include "boost/multi_array/algorithm.hpp" ++#include "boost/multi_array/allocators.hpp" ++#include "boost/core/empty_value.hpp" + #include "boost/array.hpp" + #include "boost/mpl/if.hpp" + #include "boost/type_traits.hpp" +@@ -114,8 +119,10 @@ struct disable_multi_array_impl + template + class multi_array : +- public multi_array_ref ++ public multi_array_ref, ++ private boost::empty_value + { ++ typedef boost::empty_value alloc_base; + typedef multi_array_ref super_type; + public: + typedef typename super_type::value_type value_type; +@@ -142,22 +149,25 @@ class multi_array : + typedef boost::detail::multi_array::multi_array_view type; + }; + +- explicit multi_array() : ++ explicit multi_array(const Allocator& alloc = Allocator()) : + super_type((T*)initial_base_,c_storage_order(), +- /*index_bases=*/0, /*extents=*/0) { ++ /*index_bases=*/0, /*extents=*/0), ++ alloc_base(boost::empty_init_t(),alloc) { + allocate_space(); + } + + template + explicit multi_array( +- ExtentList const& extents ++ ExtentList const& extents, ++ const Allocator& alloc = Allocator() + #ifdef BOOST_NO_FUNCTION_TEMPLATE_ORDERING + , typename mpl::if_< + detail::multi_array::is_multi_array_impl, + int&,int>::type* = 0 + #endif + ) : +- super_type((T*)initial_base_,extents) { ++ super_type((T*)initial_base_,extents), ++ alloc_base(boost::empty_init_t(),alloc) { + boost::function_requires< + detail::multi_array::CollectionConcept >(); + allocate_space(); +@@ -167,7 +177,8 @@ class multi_array : + template + explicit multi_array(ExtentList const& extents, + const general_storage_order& so) : +- super_type((T*)initial_base_,extents,so) { ++ super_type((T*)initial_base_,extents,so), ++ alloc_base(boost::empty_init_t()) { + boost::function_requires< + detail::multi_array::CollectionConcept >(); + allocate_space(); +@@ -177,7 +188,8 @@ class multi_array : + explicit multi_array(ExtentList const& extents, + const general_storage_order& so, + Allocator const& alloc) : +- super_type((T*)initial_base_,extents,so), allocator_(alloc) { ++ super_type((T*)initial_base_,extents,so), ++ alloc_base(boost::empty_init_t(),alloc) { + boost::function_requires< + detail::multi_array::CollectionConcept >(); + allocate_space(); +@@ -185,8 +197,10 @@ class multi_array : + + + explicit multi_array(const detail::multi_array +- ::extent_gen& ranges) : +- super_type((T*)initial_base_,ranges) { ++ ::extent_gen& ranges, ++ const Allocator& alloc = Allocator()) : ++ super_type((T*)initial_base_,ranges), ++ alloc_base(boost::empty_init_t(),alloc) { + + allocate_space(); + } +@@ -195,7 +209,8 @@ class multi_array : + explicit multi_array(const detail::multi_array + ::extent_gen& ranges, + const general_storage_order& so) : +- super_type((T*)initial_base_,ranges,so) { ++ super_type((T*)initial_base_,ranges,so), ++ alloc_base(boost::empty_init_t()) { + + allocate_space(); + } +@@ -205,13 +220,15 @@ class multi_array : + ::extent_gen& ranges, + const general_storage_order& so, + Allocator const& alloc) : +- super_type((T*)initial_base_,ranges,so), allocator_(alloc) { ++ super_type((T*)initial_base_,ranges,so), ++ alloc_base(boost::empty_init_t(),alloc) { + + allocate_space(); + } + + multi_array(const multi_array& rhs) : +- super_type(rhs), allocator_(rhs.allocator_) { ++ super_type(rhs), ++ alloc_base(static_cast(rhs)) { + allocate_space(); + boost::detail::multi_array::copy_n(rhs.base_,rhs.num_elements(),base_); + } +@@ -228,8 +245,10 @@ class multi_array : + #ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING + template + multi_array(const const_multi_array_ref& rhs, +- const general_storage_order& so = c_storage_order()) +- : super_type(0,so,rhs.index_bases(),rhs.shape()) ++ const general_storage_order& so = c_storage_order(), ++ const Allocator& alloc = Allocator()) ++ : super_type(0,so,rhs.index_bases(),rhs.shape()), ++ alloc_base(boost::empty_init_t(),alloc) + { + allocate_space(); + // Warning! storage order may change, hence the following copy technique. +@@ -239,8 +258,10 @@ class multi_array : + template + multi_array(const detail::multi_array:: + const_sub_array& rhs, +- const general_storage_order& so = c_storage_order()) +- : super_type(0,so,rhs.index_bases(),rhs.shape()) ++ const general_storage_order& so = c_storage_order(), ++ const Allocator& alloc = Allocator()) ++ : super_type(0,so,rhs.index_bases(),rhs.shape()), ++ alloc_base(boost::empty_init_t(),alloc) + { + allocate_space(); + std::copy(rhs.begin(),rhs.end(),this->begin()); +@@ -250,8 +271,10 @@ class multi_array : + template + multi_array(const detail::multi_array:: + const_multi_array_view& rhs, +- const general_storage_order& so = c_storage_order()) +- : super_type(0,so,rhs.index_bases(),rhs.shape()) ++ const general_storage_order& so = c_storage_order(), ++ const Allocator& alloc = Allocator()) ++ : super_type(0,so,rhs.index_bases(),rhs.shape()), ++ alloc_base(boost::empty_init_t(),alloc) + { + allocate_space(); + std::copy(rhs.begin(),rhs.end(),this->begin()); +@@ -261,8 +284,10 @@ class multi_array : + // More limited support for MSVC + + +- multi_array(const const_multi_array_ref& rhs) +- : super_type(0,c_storage_order(),rhs.index_bases(),rhs.shape()) ++ multi_array(const const_multi_array_ref& rhs, ++ const Allocator& alloc = Allocator()) ++ : super_type(0,c_storage_order(),rhs.index_bases(),rhs.shape()), ++ alloc_base(boost::empty_init_t(),alloc) + { + allocate_space(); + // Warning! storage order may change, hence the following copy technique. +@@ -270,8 +295,10 @@ class multi_array : + } + + multi_array(const const_multi_array_ref& rhs, +- const general_storage_order& so) +- : super_type(0,so,rhs.index_bases(),rhs.shape()) ++ const general_storage_order& so, ++ const Allocator& alloc = Allocator()) ++ : super_type(0,so,rhs.index_bases(),rhs.shape()), ++ alloc_base(boost::empty_init_t(),alloc) + { + allocate_space(); + // Warning! storage order may change, hence the following copy technique. +@@ -279,8 +306,10 @@ class multi_array : + } + + multi_array(const detail::multi_array:: +- const_sub_array& rhs) +- : super_type(0,c_storage_order(),rhs.index_bases(),rhs.shape()) ++ const_sub_array& rhs, ++ const Allocator& alloc = Allocator()) ++ : super_type(0,c_storage_order(),rhs.index_bases(),rhs.shape()), ++ alloc_base(boost::empty_init_t(),alloc) + { + allocate_space(); + std::copy(rhs.begin(),rhs.end(),this->begin()); +@@ -288,8 +317,10 @@ class multi_array : + + multi_array(const detail::multi_array:: + const_sub_array& rhs, +- const general_storage_order& so) +- : super_type(0,so,rhs.index_bases(),rhs.shape()) ++ const general_storage_order& so, ++ const Allocator& alloc = Allocator()) ++ : super_type(0,so,rhs.index_bases(),rhs.shape()), ++ alloc_base(boost::empty_init_t(),alloc) + { + allocate_space(); + std::copy(rhs.begin(),rhs.end(),this->begin()); +@@ -297,8 +328,10 @@ class multi_array : + + + multi_array(const detail::multi_array:: +- const_multi_array_view& rhs) +- : super_type(0,c_storage_order(),rhs.index_bases(),rhs.shape()) ++ const_multi_array_view& rhs, ++ const Allocator& alloc = Allocator()) ++ : super_type(0,c_storage_order(),rhs.index_bases(),rhs.shape()), ++ alloc_base(boost::empty_init_t(),alloc) + { + allocate_space(); + std::copy(rhs.begin(),rhs.end(),this->begin()); +@@ -306,8 +339,10 @@ class multi_array : + + multi_array(const detail::multi_array:: + const_multi_array_view& rhs, +- const general_storage_order& so) +- : super_type(0,so,rhs.index_bases(),rhs.shape()) ++ const general_storage_order& so, ++ const Allocator& alloc = Allocator()) ++ : super_type(0,so,rhs.index_bases(),rhs.shape()), ++ alloc_base(boost::empty_init_t(),alloc) + { + allocate_space(); + std::copy(rhs.begin(),rhs.end(),this->begin()); +@@ -316,8 +351,10 @@ class multi_array : + #endif // !BOOST_NO_FUNCTION_TEMPLATE_ORDERING + + // Thes constructors are necessary because of more exact template matches. +- multi_array(const multi_array_ref& rhs) +- : super_type(0,c_storage_order(),rhs.index_bases(),rhs.shape()) ++ multi_array(const multi_array_ref& rhs, ++ const Allocator& alloc = Allocator()) ++ : super_type(0,c_storage_order(),rhs.index_bases(),rhs.shape()), ++ alloc_base(boost::empty_init_t(),alloc) + { + allocate_space(); + // Warning! storage order may change, hence the following copy technique. +@@ -325,8 +362,10 @@ class multi_array : + } + + multi_array(const multi_array_ref& rhs, +- const general_storage_order& so) +- : super_type(0,so,rhs.index_bases(),rhs.shape()) ++ const general_storage_order& so, ++ const Allocator& alloc = Allocator()) ++ : super_type(0,so,rhs.index_bases(),rhs.shape()), ++ alloc_base(boost::empty_init_t(),alloc) + { + allocate_space(); + // Warning! storage order may change, hence the following copy technique. +@@ -335,8 +374,10 @@ class multi_array : + + + multi_array(const detail::multi_array:: +- sub_array& rhs) +- : super_type(0,c_storage_order(),rhs.index_bases(),rhs.shape()) ++ sub_array& rhs, ++ const Allocator& alloc = Allocator()) ++ : super_type(0,c_storage_order(),rhs.index_bases(),rhs.shape()), ++ alloc_base(boost::empty_init_t(),alloc) + { + allocate_space(); + std::copy(rhs.begin(),rhs.end(),this->begin()); +@@ -344,8 +385,10 @@ class multi_array : + + multi_array(const detail::multi_array:: + sub_array& rhs, +- const general_storage_order& so) +- : super_type(0,so,rhs.index_bases(),rhs.shape()) ++ const general_storage_order& so, ++ const Allocator& alloc = Allocator()) ++ : super_type(0,so,rhs.index_bases(),rhs.shape()), ++ alloc_base(boost::empty_init_t(),alloc) + { + allocate_space(); + std::copy(rhs.begin(),rhs.end(),this->begin()); +@@ -353,8 +396,10 @@ class multi_array : + + + multi_array(const detail::multi_array:: +- multi_array_view& rhs) +- : super_type(0,c_storage_order(),rhs.index_bases(),rhs.shape()) ++ multi_array_view& rhs, ++ const Allocator& alloc = Allocator()) ++ : super_type(0,c_storage_order(),rhs.index_bases(),rhs.shape()), ++ alloc_base(boost::empty_init_t(),alloc) + { + allocate_space(); + std::copy(rhs.begin(),rhs.end(),this->begin()); +@@ -362,8 +407,10 @@ class multi_array : + + multi_array(const detail::multi_array:: + multi_array_view& rhs, +- const general_storage_order& so) +- : super_type(0,so,rhs.index_bases(),rhs.shape()) ++ const general_storage_order& so, ++ const Allocator& alloc = Allocator()) ++ : super_type(0,so,rhs.index_bases(),rhs.shape()), ++ alloc_base(boost::empty_init_t(),alloc) + { + allocate_space(); + std::copy(rhs.begin(),rhs.end(),this->begin()); +@@ -408,7 +455,7 @@ class multi_array : + + + // build a multi_array with the specs given +- multi_array new_array(ranges,this->storage_order()); ++ multi_array new_array(ranges,this->storage_order(),allocator()); + + + // build a view of tmp with the minimum extents +@@ -454,6 +501,7 @@ class multi_array : + using std::swap; + // Swap the internals of these arrays. + swap(this->super_type::base_,new_array.super_type::base_); ++ swap(this->allocator(),new_array.allocator()); + swap(this->storage_,new_array.storage_); + swap(this->extent_list_,new_array.extent_list_); + swap(this->stride_list_,new_array.stride_list_); +@@ -461,7 +509,6 @@ class multi_array : + swap(this->origin_offset_,new_array.origin_offset_); + swap(this->directional_offset_,new_array.directional_offset_); + swap(this->num_elements_,new_array.num_elements_); +- swap(this->allocator_,new_array.allocator_); + swap(this->base_,new_array.base_); + swap(this->allocated_elements_,new_array.allocated_elements_); + +@@ -474,26 +521,43 @@ class multi_array : + } + + private: ++ friend inline bool operator==(const multi_array& a, const multi_array& b) { ++ return a.base() == b.base(); ++ } ++ ++ friend inline bool operator!=(const multi_array& a, const multi_array& b) { ++ return !(a == b); ++ } ++ ++ const super_type& base() const { ++ return *this; ++ } ++ ++ const Allocator& allocator() const { ++ return alloc_base::get(); ++ } ++ ++ Allocator& allocator() { ++ return alloc_base::get(); ++ } ++ + void allocate_space() { +- typename Allocator::const_pointer no_hint=0; +- base_ = allocator_.allocate(this->num_elements(),no_hint); ++ base_ = allocator().allocate(this->num_elements()); + this->set_base_ptr(base_); + allocated_elements_ = this->num_elements(); +- std::uninitialized_fill_n(base_,allocated_elements_,T()); ++ detail::multi_array::construct(allocator(),base_,base_+allocated_elements_); + } + + void deallocate_space() { + if(base_) { +- for(T* i = base_; i != base_+allocated_elements_; ++i) +- allocator_.destroy(i); +- allocator_.deallocate(base_,allocated_elements_); ++ detail::multi_array::destroy(allocator(),base_,base_+allocated_elements_); ++ allocator().deallocate(base_,allocated_elements_); + } + } + + typedef boost::array size_list; + typedef boost::array index_list; + +- Allocator allocator_; + T* base_; + size_type allocated_elements_; + enum {initial_base_ = 0}; +diff --git a/include/boost/multi_array/allocators.hpp b/include/boost/multi_array/allocators.hpp +new file mode 100644 +index 00000000..46914646 +--- /dev/null ++++ b/include/boost/multi_array/allocators.hpp +@@ -0,0 +1,72 @@ ++// Copyright 2018 Glen Joseph Fernandes ++// (glenjofe@gmail.com) ++// ++// Distributed under the Boost Software License, Version 1.0. ++// (See accompanying file LICENSE_1_0.txt or copy at ++// http://www.boost.org/LICENSE_1_0.txt) ++ ++#ifndef BOOST_MULTI_ARRAY_ALLOCATORS_HPP ++#define BOOST_MULTI_ARRAY_ALLOCATORS_HPP ++ ++#include ++#if !defined(BOOST_NO_CXX11_ALLOCATOR) ++#include ++#else ++#include ++#endif ++ ++namespace boost { ++namespace detail { ++namespace multi_array { ++ ++template ++inline void destroy(A& allocator, T* ptr, T* end) ++{ ++ for (; ptr != end; ++ptr) { ++#if !defined(BOOST_NO_CXX11_ALLOCATOR) ++ std::allocator_traits::destroy(allocator,ptr); ++#else ++ ptr->~T(); ++#endif ++ } ++} ++ ++template ++inline void construct(A& allocator, T* ptr) ++{ ++#if !defined(BOOST_NO_CXX11_ALLOCATOR) ++ std::allocator_traits::construct(allocator,ptr); ++#else ++ ::new(static_cast(ptr)) T(); ++#endif ++} ++ ++#if !defined(BOOST_NO_EXCEPTIONS) ++template ++inline void construct(A& allocator, T* ptr, T* end) ++{ ++ T* start = ptr; ++ try { ++ for (; ptr != end; ++ptr) { ++ boost::detail::multi_array::construct(allocator,ptr); ++ } ++ } catch (...) { ++ boost::detail::multi_array::destroy(allocator,start,ptr); ++ throw; ++ } ++} ++#else ++template ++inline void construct(A& allocator, T* ptr, T* end) ++{ ++ for (; ptr != end; ++ptr) { ++ boost::detail::multi_array::construct(allocator,ptr); ++ } ++} ++#endif ++ ++} // multi_array ++} // detail ++} // boost ++ ++#endif diff --git a/1008-Use-boost::allocator_rebind-instead-of-A::template-rebind.patch b/1008-Use-boost::allocator_rebind-instead-of-A::template-rebind.patch new file mode 100644 index 0000000..9452104 --- /dev/null +++ b/1008-Use-boost::allocator_rebind-instead-of-A::template-rebind.patch @@ -0,0 +1,33 @@ +From 6fba6e5de3a5d9b0675a875fdac8aad9238d6dd8 Mon Sep 17 00:00:00 2001 +From: Glen Fernandes +Date: Thu, 21 May 2020 10:46:47 -0400 +Subject: [PATCH] Use boost::allocator_rebind instead of A::template + rebind::other + +--- + include/boost/bimap/detail/bimap_core.hpp | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/include/boost/bimap/detail/bimap_core.hpp b/include/boost/bimap/detail/bimap_core.hpp +index 27a8fc7..0d2ca99 100644 +--- a/include/boost/bimap/detail/bimap_core.hpp ++++ b/include/boost/bimap/detail/bimap_core.hpp +@@ -47,6 +47,7 @@ + + #include + #include ++#include + + namespace boost { + namespace bimaps { +@@ -404,8 +405,8 @@ class bimap_core + < + relation, + core_indices, +- BOOST_DEDUCED_TYPENAME parameters::allocator:: +- BOOST_NESTED_TEMPLATE rebind::other ++ BOOST_DEDUCED_TYPENAME boost::allocator_rebind::type + + > core_type; + diff --git a/1009-Implement-allocator-access-utilities.patch b/1009-Implement-allocator-access-utilities.patch new file mode 100644 index 0000000..c2aae20 --- /dev/null +++ b/1009-Implement-allocator-access-utilities.patch @@ -0,0 +1,1661 @@ +From c31e23b36294bc3958b04deef62123abce0204b9 Mon Sep 17 00:00:00 2001 +From: Glen Fernandes +Date: Mon, 13 Apr 2020 01:43:43 -0400 +Subject: [PATCH] Implement allocator access utilities + +--- + doc/allocator_access.qbk | 244 +++++++++ + doc/core.qbk | 1 + + include/boost/core/allocator_access.hpp | 545 +++++++++++++++++++++ + test/Jamfile.v2 | 18 + + test/allocator_allocate_hint_test.cpp | 61 +++ + test/allocator_allocate_test.cpp | 31 ++ + test/allocator_const_pointer_test.cpp | 30 ++ + test/allocator_const_void_pointer_test.cpp | 28 ++ + test/allocator_construct_test.cpp | 49 ++ + test/allocator_deallocate_test.cpp | 31 ++ + test/allocator_destroy_test.cpp | 62 +++ + test/allocator_difference_type_test.cpp | 28 ++ + test/allocator_is_always_equal_test.cpp | 36 ++ + test/allocator_max_size_test.cpp | 35 ++ + test/allocator_pocca_test.cpp | 27 + + test/allocator_pocma_test.cpp | 27 + + test/allocator_pocs_test.cpp | 27 + + test/allocator_pointer_test.cpp | 28 ++ + test/allocator_rebind_test.cpp | 30 ++ + test/allocator_size_type_test.cpp | 34 ++ + test/allocator_soccc_test.cpp | 40 ++ + test/allocator_value_type_test.cpp | 21 + + test/allocator_void_pointer_test.cpp | 28 ++ + 23 files changed, 1461 insertions(+) + create mode 100644 doc/allocator_access.qbk + create mode 100644 include/boost/core/allocator_access.hpp + create mode 100644 test/allocator_allocate_hint_test.cpp + create mode 100644 test/allocator_allocate_test.cpp + create mode 100644 test/allocator_const_pointer_test.cpp + create mode 100644 test/allocator_const_void_pointer_test.cpp + create mode 100644 test/allocator_construct_test.cpp + create mode 100644 test/allocator_deallocate_test.cpp + create mode 100644 test/allocator_destroy_test.cpp + create mode 100644 test/allocator_difference_type_test.cpp + create mode 100644 test/allocator_is_always_equal_test.cpp + create mode 100644 test/allocator_max_size_test.cpp + create mode 100644 test/allocator_pocca_test.cpp + create mode 100644 test/allocator_pocma_test.cpp + create mode 100644 test/allocator_pocs_test.cpp + create mode 100644 test/allocator_pointer_test.cpp + create mode 100644 test/allocator_rebind_test.cpp + create mode 100644 test/allocator_size_type_test.cpp + create mode 100644 test/allocator_soccc_test.cpp + create mode 100644 test/allocator_value_type_test.cpp + create mode 100644 test/allocator_void_pointer_test.cpp + +diff --git a/doc/allocator_access.qbk b/doc/allocator_access.qbk +new file mode 100644 +index 0000000..69559c6 +--- /dev/null ++++ b/doc/allocator_access.qbk +@@ -0,0 +1,244 @@ ++[/ ++Copyright 2020 Glen Joseph Fernandes ++(glenjofe@gmail.com) ++ ++Distributed under the Boost Software License, Version 1.0. ++(http://www.boost.org/LICENSE_1_0.txt) ++] ++ ++[section Allocator Access] ++ ++[simplesect Authors] ++ ++* Glen Fernandes ++ ++[endsimplesect] ++ ++[section Overview] ++ ++The header `` provides the class and function ++templates to simplify allocator use. It provides the same functionality as the ++C++ standard library `std::allocator_traits` but with individual templates for ++each allocator feature. ++ ++This implementation supports C++03 and above. These facilities also simplify ++existing libraries by avoiding having to check for `BOOST_NO_CXX11_ALLOCATOR` ++and conditionally use `std::allocator_traits`. ++ ++[endsect] ++ ++[section Examples] ++ ++The following example shows these utilities used in the definition of ++an allocator-aware container class: ++ ++``` ++template > ++class container ++ : boost::empty_value::type> { ++public: ++ typedef T value_type; ++ typedef A allocator_type; ++ typedef typename boost::allocator_size_type::type size_type; ++ typedef typename boost::allocator_difference_type::type difference_type; ++ typedef value_type& reference; ++ typedef const value_type& const_reference; ++ typedef typename boost::allocator_pointer::type pointer; ++ typedef typename boost::allocator_const_pointer::type const_pointer; ++ // ... ++}; ++``` ++ ++In C++11 or above, aliases such as `boost::allocator_pointer_t` can be used ++instead of `typename boost::allocator_pointer::type`. ++ ++[endsect] ++ ++[section Reference] ++ ++``` ++namespace boost { ++ ++template ++struct allocator_value_type; ++ ++template ++using allocator_value_type_t = typename allocator_value_type::type; ++ ++template ++struct allocator_pointer; ++ ++template ++using allocator_pointer_t = typename allocator_pointer::type; ++ ++template ++struct allocator_const_pointer; ++ ++template ++using allocator_const_pointer_t = typename allocator_const_pointer::type; ++ ++template ++struct allocator_void_pointer; ++ ++template ++using allocator_void_pointer_t = typename allocator_void_pointer::type; ++ ++template ++struct allocator_const_void_pointer; ++ ++template ++using allocator_const_void_pointer_t = ++ typename allocator_const_void_pointer::type; ++ ++template ++struct allocator_difference_type; ++ ++template ++using allocator_difference_type_t = ++ typename allocator_difference_type::type; ++ ++template ++struct allocator_size_type; ++ ++template ++using allocator_size_type_t = typename allocator_size_type::type; ++ ++template ++struct allocator_propagate_on_container_copy_assignment; ++ ++template ++using allocator_propagate_on_container_copy_assignment_t = ++ typename allocator_propagate_on_container_copy_assignment::type; ++ ++template ++struct allocator_propagate_on_container_move_assignment; ++ ++template ++using allocator_propagate_on_container_move_assignment_t = ++ typename allocator_propagate_on_container_move_assignment::type; ++ ++template ++struct allocator_propagate_on_container_swap; ++ ++template ++using allocator_propagate_on_container_swap_t = ++ typename allocator_propagate_on_container_swap::type; ++ ++template ++struct allocator_is_always_equal; ++ ++template ++using allocator_is_always_equal_t = ++ typename allocator_is_always_equal::type; ++ ++template ++struct allocator_rebind; ++ ++template ++using allocator_rebind_t = typename allocator_rebind::type; ++ ++template ++allocator_pointer_t allocator_allocate(A& a, allocator_size_type_t n); ++ ++template ++allocator_pointer_t allocator_allocate(A& a, allocator_size_type_t n, ++ allocator_const_void_pointer_t hint); ++ ++template ++void allocator_deallocate(A& a, allocator_pointer_t p, ++ allocator_size_type_t n); ++ ++template ++void allocator_construct(A& a, T*p, Args&&... args); ++ ++template ++void allocator_destroy(A& a, T* p); ++ ++template ++allocator_size_type_t allocator_max_size(const A& a); ++ ++template ++A allocator_select_on_container_copy_construction(const A& a); ++ ++} // boost ++``` ++ ++[section Types] ++ ++[variablelist ++[[`template struct allocator_value_type;`] ++[The member `type` is `A::value_type`.]] ++[[`template struct allocator_pointer;`] ++[The member `type` is `A::pointer` if valid, otherwise `A::value_type*`.]] ++[[`template struct allocator_const_pointer;`] ++[The member `type` is `A::const_pointer` if valid, otherwise ++`pointer_traits >::rebind >`.]] ++[[`template struct allocator_void_pointer;`] ++[The member `type` is `A::void_pointer` if valid, otherwise ++`pointer_traits >::rebind`.]] ++[[`template struct allocator_const_void_pointer;`] ++[The member `type` is `A::const_void_pointer` if valid, otherwise ++`pointer_traits >::rebind`.]] ++[[`template struct allocator_difference_type;`] ++[The member `type` is `A::difference_type` if valid, otherwise ++`pointer_traits >::difference_type`.]] ++[[`template struct allocator_size_type;`] ++[The member `type` is `A::size_type` if valid, otherwise ++`std::make_unsigned_t >`.]] ++[[`template struct allocator_propagate_on_container_copy_assignment;`] ++[The member `type` is `A::propagate_on_container_copy_assignment` if valid, ++otherwise `std::false_type`.]] ++[[`template struct allocator_propagate_on_container_move_assignment;`] ++[The member `type` is `A::propagate_on_container_move_assignment` if valid, ++otherwise `std::false_type`.]] ++[[`template struct allocator_propagate_on_container_swap;`] ++[The member `type` is `A::propagate_on_container_swap` if valid, otherwise ++`std::false_type`.]] ++[[`template struct allocator_is_always_equal;`] ++[The member `type` is `A::is_always_equal` if valid, otherwise ++`std::is_empty::type`.]] ++[[`template struct allocator_rebind;`] ++[The member `type` is `A::rebind::other` if valid, otherwise `A` ++if this `A` is `A`.]]] ++ ++[endsect] ++ ++[section Functions] ++ ++[variablelist ++[[`template ++allocator_pointer_t allocator_allocate(A& a, allocator_size_type_t n);`] ++[Calls `a.allcoate(n)`.]] ++[[`template allocator_pointer_t allocator_allocate(A& a, ++allocator_size_type_t n, allocator_const_void_pointer_t hint);`] ++[Calls `a.allocate(n, hint)` if valid, otherwise calls `a.allocate(n)`.]] ++[[`template void allocator_deallocate(A& a, allocator_pointer_t p, ++allocator_size_type_t n);`] ++[Calls `a.deallocate(p, n)`.]] ++[[`template ++void allocator_construct(A& a, T*p, Args&&... args);`] ++[Calls `a.construct(p, std::forward(args)...)` if valid, otherwise calls ++`::new(static_cast(p)) T(std::forward(args)...)`.]] ++[[`template void allocator_destroy(A& a, T* p);`] ++[Calls `a.destroy(p)` if valid, otherwise calls `p->~T()`.]] ++[[`template allocator_size_type_t allocator_max_size(const A& a);`] ++[Returns `a.max_size()` if valid, otehrwise returns ++`std::numeric_limits >::max() / ++sizeof(A::value_type)`.]] ++[[`template A allocator_select_on_container_copy_construction(const ++A& a);`] ++[Returns `a.select_on_container_copy_construction()` if valid, otherwise ++returns `a`.]]] ++ ++[endsect] ++ ++[endsect] ++ ++[section Acknowledgments] ++ ++Glen Fernandes implemented the allocator access utilities. ++ ++[endsect] ++ ++[endsect] +diff --git a/doc/core.qbk b/doc/core.qbk +index 1aac342..a51d6f9 100644 +--- a/boost/libs/core/doc/core.qbk ++++ b/boost/libs/core/doc/core.qbk +@@ -39,6 +39,7 @@ criteria for inclusion is that the utility component be: + [endsect] + + [include addressof.qbk] ++[include allocator_access.qbk] + [include checked_delete.qbk] + [include demangle.qbk] + [include empty_value.qbk] +diff --git a/include/boost/core/allocator_access.hpp b/include/boost/core/allocator_access.hpp +new file mode 100644 +index 0000000..4298e5b +--- /dev/null ++++ b/include/boost/core/allocator_access.hpp +@@ -0,0 +1,545 @@ ++/* ++Copyright 2020 Glen Joseph Fernandes ++(glenjofe@gmail.com) ++ ++Distributed under the Boost Software License, Version 1.0. ++(http://www.boost.org/LICENSE_1_0.txt) ++*/ ++#ifndef BOOST_CORE_ALLOCATOR_ACCESS_HPP ++#define BOOST_CORE_ALLOCATOR_ACCESS_HPP ++ ++#include ++#include ++#include ++#if !defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS) ++#include ++#endif ++#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) ++#include ++#endif ++ ++#if !defined(BOOST_NO_CXX11_DECLTYPE) && \ ++ !defined(BOOST_NO_SFINAE_EXPR) && \ ++ (!defined(BOOST_MSVC) || BOOST_MSVC >= 1910) ++#define BOOST_CORE_ALLOCATOR_DETECTION ++#endif ++ ++namespace boost { ++ ++template ++struct allocator_value_type { ++ typedef typename A::value_type type; ++}; ++ ++namespace detail { ++ ++template ++struct alloc_void { ++ typedef void type; ++}; ++ ++} /* detail */ ++ ++template ++struct allocator_pointer { ++ typedef typename A::value_type* type; ++}; ++ ++template ++struct allocator_pointer::type> { ++ typedef typename A::pointer type; ++}; ++ ++template ++struct allocator_const_pointer { ++ typedef typename pointer_traits::type>::template ++ rebind_to::type type; ++}; ++ ++template ++struct allocator_const_pointer::type> { ++ typedef typename A::const_pointer type; ++}; ++ ++template ++struct allocator_void_pointer { ++ typedef typename pointer_traits::type>::template ++ rebind_to::type type; ++}; ++ ++template ++struct allocator_void_pointer::type> { ++ typedef typename A::void_pointer type; ++}; ++ ++template ++struct allocator_const_void_pointer { ++ typedef typename pointer_traits::type>::template ++ rebind_to::type type; ++}; ++ ++template ++struct allocator_const_void_pointer::type> { ++ typedef typename A::const_void_pointer type; ++}; ++ ++template ++struct allocator_difference_type { ++ typedef typename pointer_traits::type>::difference_type type; ++}; ++ ++template ++struct allocator_difference_type::type> { ++ typedef typename A::difference_type type; ++}; ++ ++#if !defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS) ++template ++struct allocator_size_type { ++ typedef typename std::make_unsigned::type>::type type; ++}; ++ ++template ++struct allocator_size_type::type> { ++ typedef typename A::size_type type; ++}; ++#else ++template ++struct allocator_size_type { ++ typedef typename A::size_type type; ++}; ++#endif ++ ++namespace detail { ++ ++#if !defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS) ++typedef std::false_type alloc_false_type; ++#else ++struct alloc_false_type { ++ BOOST_STATIC_CONSTEXPR bool value = false; ++}; ++#endif ++ ++} /* detail */ ++ ++template ++struct allocator_propagate_on_container_copy_assignment { ++ typedef detail::alloc_false_type type; ++}; ++ ++template ++struct allocator_propagate_on_container_copy_assignment::type> { ++ typedef typename A::propagate_on_container_copy_assignment type; ++}; ++ ++template ++struct allocator_propagate_on_container_move_assignment { ++ typedef detail::alloc_false_type type; ++}; ++ ++template ++struct allocator_propagate_on_container_move_assignment::type> { ++ typedef typename A::propagate_on_container_move_assignment type; ++}; ++ ++template ++struct allocator_propagate_on_container_swap { ++ typedef detail::alloc_false_type type; ++}; ++ ++template ++struct allocator_propagate_on_container_swap::type> { ++ typedef typename A::propagate_on_container_swap type; ++}; ++ ++#if !defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS) ++template ++struct allocator_is_always_equal { ++ typedef typename std::is_empty::type type; ++}; ++#else ++template ++struct allocator_is_always_equal { ++ typedef typename detail::alloc_false_type type; ++}; ++#endif ++ ++template ++struct allocator_is_always_equal::type> { ++ typedef typename A::is_always_equal type; ++}; ++ ++namespace detail { ++ ++template ++struct alloc_to { }; ++ ++#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) ++template class A, class T, class U, class... V> ++struct alloc_to, T> { ++ typedef A type; ++}; ++#else ++template class A, class T, class U> ++struct alloc_to, T> { ++ typedef A type; ++}; ++ ++template class A, class T, class U1, class U2> ++struct alloc_to, T> { ++ typedef A type; ++}; ++ ++template class A, class T, class U1, class U2, ++ class U3> ++struct alloc_to, T> { ++ typedef A type; ++}; ++#endif ++ ++} /* detail */ ++ ++template ++struct allocator_rebind { ++ typedef typename detail::alloc_to::type type; ++}; ++ ++template ++struct allocator_rebind::other>::type> { ++ typedef typename A::template rebind::other type; ++}; ++ ++template ++inline typename allocator_pointer::type ++allocator_allocate(A& a, typename allocator_size_type::type n) ++{ ++ return a.allocate(n); ++} ++ ++namespace detail { ++ ++template ++struct alloc_if { }; ++ ++template ++struct alloc_if { ++ typedef R type; ++}; ++ ++#if defined(BOOST_CORE_ALLOCATOR_DETECTION) ++template ++T alloc_declval() BOOST_NOEXCEPT; ++#endif ++ ++template ++struct alloc_has_allocate { ++ BOOST_STATIC_CONSTEXPR bool value = false; ++}; ++ ++#if defined(BOOST_CORE_ALLOCATOR_DETECTION) ++template ++struct alloc_has_allocate().allocate(alloc_declval::type>(), alloc_declval::type>()))>::type> { ++ BOOST_STATIC_CONSTEXPR bool value = true; ++}; ++#endif ++ ++} /* detail */ ++ ++template ++inline typename detail::alloc_if::value, ++ typename allocator_pointer::type>::type ++allocator_allocate(A& a, typename allocator_size_type::type n, ++ typename allocator_const_void_pointer::type h) ++{ ++ return a.allocate(n, h); ++} ++ ++template ++inline typename detail::alloc_if::value, ++ typename allocator_pointer::type>::type ++allocator_allocate(A& a, typename allocator_size_type::type n, ++ typename allocator_const_void_pointer::type) ++{ ++ return a.allocate(n); ++} ++ ++template ++inline void ++allocator_deallocate(A& a, typename allocator_pointer::type p, ++ typename allocator_size_type::type n) ++{ ++ a.deallocate(p, n); ++} ++ ++namespace detail { ++ ++#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) ++template ++struct alloc_types { }; ++#else ++template ++struct alloc_types { }; ++#endif ++ ++template ++struct alloc_has_construct { ++ BOOST_STATIC_CONSTEXPR bool value = false; ++}; ++ ++#if defined(BOOST_CORE_ALLOCATOR_DETECTION) ++#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) ++template ++struct alloc_has_construct, typename ++ alloc_void().construct(alloc_declval(), ++ alloc_declval()...))>::type> { ++ BOOST_STATIC_CONSTEXPR bool value = true; ++}; ++#else ++template ++struct alloc_has_construct, typename ++ alloc_void().construct(alloc_declval(), ++ alloc_declval()))>::type> { ++ BOOST_STATIC_CONSTEXPR bool value = true; ++}; ++#endif ++#endif ++ ++} /* detail */ ++ ++#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) ++#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) ++template ++inline typename detail::alloc_if >::value>::type ++allocator_construct(A& a, T*p, Args&&... args) ++{ ++ a.construct(p, std::forward(args)...); ++} ++ ++template ++inline typename detail::alloc_if >::value>::type ++allocator_construct(A&, T* p, Args&&... args) ++{ ++ ::new(static_cast(p)) T(std::forward(args)...); ++} ++#else ++template ++inline typename detail::alloc_if >::value>::type ++allocator_construct(A& a, T*p, V&& v) ++{ ++ a.construct(p, std::forward(v)); ++} ++ ++template ++inline typename detail::alloc_if >::value>::type ++allocator_construct(A&, T* p, V&& v) ++{ ++ ::new(static_cast(p)) T(std::forward(v)); ++} ++#endif ++#else ++template ++inline typename detail::alloc_if >::value>::type ++allocator_construct(A& a, T*p, const V& v) ++{ ++ a.construct(p, v); ++} ++ ++template ++inline typename detail::alloc_if >::value>::type ++allocator_construct(A&, T* p, const V& v) ++{ ++ ::new(static_cast(p)) T(v); ++} ++ ++template ++inline typename detail::alloc_if >::value>::type ++allocator_construct(A& a, T*p, V& v) ++{ ++ a.construct(p, v); ++} ++ ++template ++inline typename detail::alloc_if >::value>::type ++allocator_construct(A&, T* p, V& v) ++{ ++ ::new(static_cast(p)) T(v); ++} ++#endif ++ ++namespace detail { ++ ++template ++struct alloc_has_destroy { ++ BOOST_STATIC_CONSTEXPR bool value = false; ++}; ++ ++#if defined(BOOST_CORE_ALLOCATOR_DETECTION) ++template ++struct alloc_has_destroy(). ++ destroy(alloc_declval()))>::type> { ++ BOOST_STATIC_CONSTEXPR bool value = true; ++}; ++#endif ++ ++} /* detail */ ++ ++template ++inline typename detail::alloc_if::value>::type ++allocator_destroy(A& a, T*p) ++{ ++ a.destroy(p); ++} ++ ++template ++inline typename detail::alloc_if::value>::type ++allocator_destroy(A&, T* p) ++{ ++ p->~T(); ++ (void)p; ++} ++ ++namespace detail { ++ ++template ++struct alloc_has_max_size { ++ BOOST_STATIC_CONSTEXPR bool value = false; ++}; ++ ++#if defined(BOOST_CORE_ALLOCATOR_DETECTION) ++template ++struct alloc_has_max_size().max_size())>::type> { ++ BOOST_STATIC_CONSTEXPR bool value = true; ++}; ++#endif ++ ++} /* detail */ ++ ++template ++inline typename detail::alloc_if::value, ++ typename allocator_size_type::type>::type ++allocator_max_size(const A& a) ++{ ++ return a.max_size(); ++} ++ ++template ++inline typename detail::alloc_if::value, ++ typename allocator_size_type::type>::type ++allocator_max_size(const A&) ++{ ++ return std::numeric_limits::type>::max() / ++ sizeof(typename A::value_type); ++} ++ ++namespace detail { ++ ++template ++struct alloc_has_soccc { ++ BOOST_STATIC_CONSTEXPR bool value = false; ++}; ++ ++#if defined(BOOST_CORE_ALLOCATOR_DETECTION) ++template ++struct alloc_has_soccc().select_on_container_copy_construction())>::type> { ++ BOOST_STATIC_CONSTEXPR bool value = true; ++}; ++#endif ++ ++} /* detail */ ++ ++template ++inline typename detail::alloc_if::value, A>::type ++allocator_select_on_container_copy_construction(const A& a) ++{ ++ return a.select_on_container_copy_construction(); ++} ++ ++template ++inline typename detail::alloc_if::value, A>::type ++allocator_select_on_container_copy_construction(const A& a) ++{ ++ return a; ++} ++ ++#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) ++template ++using allocator_value_type_t = typename allocator_value_type::type; ++ ++template ++using allocator_pointer_t = typename allocator_pointer::type; ++ ++template ++using allocator_const_pointer_t = typename allocator_const_pointer::type; ++ ++template ++using allocator_void_pointer_t = typename allocator_void_pointer::type; ++ ++template ++using allocator_const_void_pointer_t = ++ typename allocator_const_void_pointer::type; ++ ++template ++using allocator_difference_type_t = ++ typename allocator_difference_type::type; ++ ++template ++using allocator_size_type_t = typename allocator_size_type::type; ++ ++template ++using allocator_propagate_on_container_copy_assignment_t = ++ typename allocator_propagate_on_container_copy_assignment::type; ++ ++template ++using allocator_propagate_on_container_move_assignment_t = ++ typename allocator_propagate_on_container_move_assignment::type; ++ ++template ++using allocator_propagate_on_container_swap_t = ++ typename allocator_propagate_on_container_swap::type; ++ ++template ++using allocator_is_always_equal_t = ++ typename allocator_is_always_equal::type; ++ ++template ++using allocator_rebind_t = typename allocator_rebind::type; ++#endif ++ ++} /* boost */ ++ ++#endif +diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 +index 4b915e6..54fc0c8 100644 +--- a/boost/libs/core/test/Jamfile.v2 ++++ b/boost/libs/core/test/Jamfile.v2 +@@ -161,6 +161,24 @@ run alloc_construct_cxx11_test.cpp ; + run pointer_traits_pointer_to_test.cpp ; + run to_address_test.cpp ; + ++run allocator_value_type_test.cpp ; ++run allocator_pointer_test.cpp ; ++run allocator_const_pointer_test.cpp ; ++run allocator_void_pointer_test.cpp ; ++run allocator_const_void_pointer_test.cpp ; ++run allocator_difference_type_test.cpp ; ++run allocator_size_type_test.cpp ; ++run allocator_pocca_test.cpp ; ++run allocator_pocma_test.cpp ; ++run allocator_pocs_test.cpp ; ++run allocator_is_always_equal_test.cpp ; ++run allocator_rebind_test.cpp ; ++run allocator_allocate_test.cpp ; ++run allocator_allocate_hint_test.cpp ; ++run allocator_deallocate_test.cpp ; ++run allocator_max_size_test.cpp ; ++run allocator_soccc_test.cpp ; ++ + run empty_value_test.cpp ; + run empty_value_size_test.cpp ; + +diff --git a/test/allocator_allocate_hint_test.cpp b/test/allocator_allocate_hint_test.cpp +new file mode 100644 +index 0000000..e5ca2f3 +--- /dev/null ++++ b/boost/libs/core/test/allocator_allocate_hint_test.cpp +@@ -0,0 +1,61 @@ ++/* ++Copyright 2020 Glen Joseph Fernandes ++(glenjofe@gmail.com) ++ ++Distributed under the Boost Software License, Version 1.0. ++(http://www.boost.org/LICENSE_1_0.txt) ++*/ ++#include ++#include ++ ++struct A1 { ++ typedef int* pointer; ++ typedef int size_type; ++ ++ A1() ++ : value() { } ++ ++ pointer allocate(size_type n) { ++ value = n; ++ return &value; ++ } ++ ++ size_type value; ++}; ++ ++#if defined(BOOST_CORE_ALLOCATOR_DETECTION) ++struct A2 { ++ typedef int* pointer; ++ typedef int size_type; ++ ++ A2() ++ : value() { } ++ ++ pointer allocate(size_type n) { ++ value = n; ++ return &value; ++ } ++ ++ pointer allocate(size_type n, const void*) { ++ value = n + 1; ++ return &value; ++ } ++ ++ size_type value; ++}; ++#endif ++ ++int main() ++{ ++ { ++ A1 a; ++ BOOST_TEST_EQ(*boost::allocator_allocate(a, 1, 0), 1); ++ } ++#if defined(BOOST_CORE_ALLOCATOR_DETECTION) ++ { ++ A2 a; ++ BOOST_TEST_EQ(*boost::allocator_allocate(a, 1, 0), 2); ++ } ++#endif ++ return boost::report_errors(); ++} +diff --git a/test/allocator_allocate_test.cpp b/test/allocator_allocate_test.cpp +new file mode 100644 +index 0000000..73ee06b +--- /dev/null ++++ b/boost/libs/core/test/allocator_allocate_test.cpp +@@ -0,0 +1,31 @@ ++/* ++Copyright 2020 Glen Joseph Fernandes ++(glenjofe@gmail.com) ++ ++Distributed under the Boost Software License, Version 1.0. ++(http://www.boost.org/LICENSE_1_0.txt) ++*/ ++#include ++#include ++ ++struct A { ++ typedef int* pointer; ++ typedef int size_type; ++ ++ A() ++ : value() { } ++ ++ pointer allocate(size_type n) { ++ value = n; ++ return &value; ++ } ++ ++ size_type value; ++}; ++ ++int main() ++{ ++ A a; ++ BOOST_TEST_EQ(*boost::allocator_allocate(a, 5), 5); ++ return boost::report_errors(); ++} +diff --git a/test/allocator_const_pointer_test.cpp b/test/allocator_const_pointer_test.cpp +new file mode 100644 +index 0000000..b8fc78d +--- /dev/null ++++ b/boost/libs/core/test/allocator_const_pointer_test.cpp +@@ -0,0 +1,30 @@ ++/* ++Copyright 2020 Glen Joseph Fernandes ++(glenjofe@gmail.com) ++ ++Distributed under the Boost Software License, Version 1.0. ++(http://www.boost.org/LICENSE_1_0.txt) ++*/ ++#include ++#include ++#include ++ ++struct A1 { ++ typedef char value_type; ++ typedef int* pointer; ++}; ++ ++struct A2 { ++ typedef char value_type; ++ typedef int* pointer; ++ typedef const bool* const_pointer; ++}; ++ ++int main() ++{ ++ BOOST_TEST_TRAIT_TRUE((boost::core::is_same::type>)); ++ BOOST_TEST_TRAIT_TRUE((boost::core::is_same::type>)); ++ return boost::report_errors(); ++} +diff --git a/test/allocator_const_void_pointer_test.cpp b/test/allocator_const_void_pointer_test.cpp +new file mode 100644 +index 0000000..ed39feb +--- /dev/null ++++ b/boost/libs/core/test/allocator_const_void_pointer_test.cpp +@@ -0,0 +1,28 @@ ++/* ++Copyright 2020 Glen Joseph Fernandes ++(glenjofe@gmail.com) ++ ++Distributed under the Boost Software License, Version 1.0. ++(http://www.boost.org/LICENSE_1_0.txt) ++*/ ++#include ++#include ++#include ++ ++struct A1 { ++ typedef int* pointer; ++}; ++ ++struct A2 { ++ typedef int* pointer; ++ typedef const bool* const_void_pointer; ++}; ++ ++int main() ++{ ++ BOOST_TEST_TRAIT_TRUE((boost::core::is_same::type>)); ++ BOOST_TEST_TRAIT_TRUE((boost::core::is_same::type>)); ++ return boost::report_errors(); ++} +diff --git a/test/allocator_construct_test.cpp b/test/allocator_construct_test.cpp +new file mode 100644 +index 0000000..8e7be0b +--- /dev/null ++++ b/boost/libs/core/test/allocator_construct_test.cpp +@@ -0,0 +1,49 @@ ++/* ++Copyright 2020 Glen Joseph Fernandes ++(glenjofe@gmail.com) ++ ++Distributed under the Boost Software License, Version 1.0. ++(http://www.boost.org/LICENSE_1_0.txt) ++*/ ++#include ++#include ++#include ++ ++struct S { ++ S(int v) ++ : value(v) { } ++ ++ int value; ++}; ++ ++struct A1 { }; ++ ++#if defined(BOOST_CORE_ALLOCATOR_DETECTION) ++struct A2 { ++ void construct(S* p, int v) { ++ new(p) S(v + 1); ++ } ++}; ++#endif ++ ++int main() ++{ ++ boost::default_allocator d; ++ { ++ S* p = d.allocate(1); ++ A1 a; ++ boost::allocator_construct(a, p, 1); ++ BOOST_TEST_EQ(p->value, 1); ++ d.deallocate(p, 1); ++ } ++#if defined(BOOST_CORE_ALLOCATOR_DETECTION) ++ { ++ S* p = d.allocate(1); ++ A2 a; ++ boost::allocator_construct(a, p, 1); ++ BOOST_TEST_EQ(p->value, 2); ++ d.deallocate(p, 1); ++ } ++#endif ++ return boost::report_errors(); ++} +diff --git a/test/allocator_deallocate_test.cpp b/test/allocator_deallocate_test.cpp +new file mode 100644 +index 0000000..83a4bda +--- /dev/null ++++ b/boost/libs/core/test/allocator_deallocate_test.cpp +@@ -0,0 +1,31 @@ ++/* ++Copyright 2020 Glen Joseph Fernandes ++(glenjofe@gmail.com) ++ ++Distributed under the Boost Software License, Version 1.0. ++(http://www.boost.org/LICENSE_1_0.txt) ++*/ ++#include ++#include ++ ++struct A { ++ typedef int* pointer; ++ typedef int size_type; ++ ++ A() ++ : value() { } ++ ++ void deallocate(pointer, size_type n) { ++ value = n; ++ } ++ ++ size_type value; ++}; ++ ++int main() ++{ ++ A a; ++ boost::allocator_deallocate(a, 0, 5); ++ BOOST_TEST_EQ(a.value, 5); ++ return boost::report_errors(); ++} +diff --git a/test/allocator_destroy_test.cpp b/test/allocator_destroy_test.cpp +new file mode 100644 +index 0000000..5ecc6c0 +--- /dev/null ++++ b/boost/libs/core/test/allocator_destroy_test.cpp +@@ -0,0 +1,62 @@ ++/* ++Copyright 2020 Glen Joseph Fernandes ++(glenjofe@gmail.com) ++ ++Distributed under the Boost Software License, Version 1.0. ++(http://www.boost.org/LICENSE_1_0.txt) ++*/ ++#include ++#include ++#include ++ ++struct S { ++ static int count; ++ ++ S() { ++ ++count; ++ } ++ ++ S(const S&) { ++ ++count; ++ } ++ ++ ~S() { ++ --count; ++ } ++}; ++ ++int S::count = 0; ++ ++struct A1 { }; ++ ++#if defined(BOOST_CORE_ALLOCATOR_DETECTION) ++struct A2 { ++ void destroy(S*) { ++ ++S::count; ++ } ++}; ++#endif ++ ++int main() ++{ ++ boost::default_allocator d; ++ { ++ S* p = d.allocate(1); ++ new(p) S; ++ A1 a; ++ boost::allocator_destroy(a, p); ++ BOOST_TEST_EQ(S::count, 0); ++ d.deallocate(p, 1); ++ } ++#if defined(BOOST_CORE_ALLOCATOR_DETECTION) ++ { ++ S* p = d.allocate(1); ++ new(p) S; ++ A2 a; ++ boost::allocator_destroy(a, p); ++ BOOST_TEST_EQ(S::count, 2); ++ d.deallocate(p, 1); ++ } ++#endif ++ return boost::report_errors(); ++} +diff --git a/test/allocator_difference_type_test.cpp b/test/allocator_difference_type_test.cpp +new file mode 100644 +index 0000000..d40ef46 +--- /dev/null ++++ b/boost/libs/core/test/allocator_difference_type_test.cpp +@@ -0,0 +1,28 @@ ++/* ++Copyright 2020 Glen Joseph Fernandes ++(glenjofe@gmail.com) ++ ++Distributed under the Boost Software License, Version 1.0. ++(http://www.boost.org/LICENSE_1_0.txt) ++*/ ++#include ++#include ++#include ++ ++struct A1 { ++ typedef char* pointer; ++}; ++ ++struct A2 { ++ typedef char* pointer; ++ typedef int difference_type; ++}; ++ ++int main() ++{ ++ BOOST_TEST_TRAIT_TRUE((boost::core::is_same::type>)); ++ BOOST_TEST_TRAIT_TRUE((boost::core::is_same::type>)); ++ return boost::report_errors(); ++} +diff --git a/test/allocator_is_always_equal_test.cpp b/test/allocator_is_always_equal_test.cpp +new file mode 100644 +index 0000000..aef2f60 +--- /dev/null ++++ b/boost/libs/core/test/allocator_is_always_equal_test.cpp +@@ -0,0 +1,36 @@ ++/* ++Copyright 2020 Glen Joseph Fernandes ++(glenjofe@gmail.com) ++ ++Distributed under the Boost Software License, Version 1.0. ++(http://www.boost.org/LICENSE_1_0.txt) ++*/ ++#include ++#include ++#include ++ ++struct A1 { ++ int value; ++}; ++ ++struct A2 { ++ struct is_always_equal { ++ BOOST_STATIC_CONSTEXPR bool value = true; ++ }; ++ ++ int value; ++}; ++ ++#if !defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS) ++struct A3 { }; ++#endif ++ ++int main() ++{ ++ BOOST_TEST_TRAIT_FALSE((boost::allocator_is_always_equal::type)); ++ BOOST_TEST_TRAIT_TRUE((boost::allocator_is_always_equal::type)); ++#if !defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS) ++ BOOST_TEST_TRAIT_TRUE((boost::allocator_is_always_equal::type)); ++#endif ++ return boost::report_errors(); ++} +diff --git a/test/allocator_max_size_test.cpp b/test/allocator_max_size_test.cpp +new file mode 100644 +index 0000000..0ad609a +--- /dev/null ++++ b/boost/libs/core/test/allocator_max_size_test.cpp +@@ -0,0 +1,35 @@ ++/* ++Copyright 2020 Glen Joseph Fernandes ++(glenjofe@gmail.com) ++ ++Distributed under the Boost Software License, Version 1.0. ++(http://www.boost.org/LICENSE_1_0.txt) ++*/ ++#include ++#include ++ ++struct A1 { ++ typedef long value_type; ++ typedef short size_type; ++}; ++ ++#if defined(BOOST_CORE_ALLOCATOR_DETECTION) ++struct A2 { ++ typedef long value_type; ++ typedef short size_type; ++ ++ size_type max_size() const { ++ return 1; ++ } ++}; ++#endif ++ ++int main() ++{ ++ BOOST_TEST_EQ(boost::allocator_max_size(A1()), ++ std::numeric_limits::max() / sizeof(A1::value_type)); ++#if defined(BOOST_CORE_ALLOCATOR_DETECTION) ++ BOOST_TEST_EQ(boost::allocator_max_size(A2()), 1); ++#endif ++ return boost::report_errors(); ++} +diff --git a/test/allocator_pocca_test.cpp b/test/allocator_pocca_test.cpp +new file mode 100644 +index 0000000..80e9e75 +--- /dev/null ++++ b/boost/libs/core/test/allocator_pocca_test.cpp +@@ -0,0 +1,27 @@ ++/* ++Copyright 2020 Glen Joseph Fernandes ++(glenjofe@gmail.com) ++ ++Distributed under the Boost Software License, Version 1.0. ++(http://www.boost.org/LICENSE_1_0.txt) ++*/ ++#include ++#include ++#include ++ ++struct A1 { }; ++ ++struct A2 { ++ struct propagate_on_container_copy_assignment { ++ BOOST_STATIC_CONSTEXPR bool value = true; ++ }; ++}; ++ ++int main() ++{ ++ BOOST_TEST_TRAIT_FALSE((boost:: ++ allocator_propagate_on_container_copy_assignment::type)); ++ BOOST_TEST_TRAIT_TRUE((boost:: ++ allocator_propagate_on_container_copy_assignment::type)); ++ return boost::report_errors(); ++} +diff --git a/test/allocator_pocma_test.cpp b/test/allocator_pocma_test.cpp +new file mode 100644 +index 0000000..c8d1a45 +--- /dev/null ++++ b/boost/libs/core/test/allocator_pocma_test.cpp +@@ -0,0 +1,27 @@ ++/* ++Copyright 2020 Glen Joseph Fernandes ++(glenjofe@gmail.com) ++ ++Distributed under the Boost Software License, Version 1.0. ++(http://www.boost.org/LICENSE_1_0.txt) ++*/ ++#include ++#include ++#include ++ ++struct A1 { }; ++ ++struct A2 { ++ struct propagate_on_container_move_assignment { ++ BOOST_STATIC_CONSTEXPR bool value = true; ++ }; ++}; ++ ++int main() ++{ ++ BOOST_TEST_TRAIT_FALSE((boost:: ++ allocator_propagate_on_container_move_assignment::type)); ++ BOOST_TEST_TRAIT_TRUE((boost:: ++ allocator_propagate_on_container_move_assignment::type)); ++ return boost::report_errors(); ++} +diff --git a/test/allocator_pocs_test.cpp b/test/allocator_pocs_test.cpp +new file mode 100644 +index 0000000..3fa94c1 +--- /dev/null ++++ b/boost/libs/core/test/allocator_pocs_test.cpp +@@ -0,0 +1,27 @@ ++/* ++Copyright 2020 Glen Joseph Fernandes ++(glenjofe@gmail.com) ++ ++Distributed under the Boost Software License, Version 1.0. ++(http://www.boost.org/LICENSE_1_0.txt) ++*/ ++#include ++#include ++#include ++ ++struct A1 { }; ++ ++struct A2 { ++ struct propagate_on_container_swap { ++ BOOST_STATIC_CONSTEXPR bool value = true; ++ }; ++}; ++ ++int main() ++{ ++ BOOST_TEST_TRAIT_FALSE((boost:: ++ allocator_propagate_on_container_swap::type)); ++ BOOST_TEST_TRAIT_TRUE((boost:: ++ allocator_propagate_on_container_swap::type)); ++ return boost::report_errors(); ++} +diff --git a/test/allocator_pointer_test.cpp b/test/allocator_pointer_test.cpp +new file mode 100644 +index 0000000..95eade2 +--- /dev/null ++++ b/boost/libs/core/test/allocator_pointer_test.cpp +@@ -0,0 +1,28 @@ ++/* ++Copyright 2020 Glen Joseph Fernandes ++(glenjofe@gmail.com) ++ ++Distributed under the Boost Software License, Version 1.0. ++(http://www.boost.org/LICENSE_1_0.txt) ++*/ ++#include ++#include ++#include ++ ++struct A1 { ++ typedef char value_type; ++}; ++ ++struct A2 { ++ typedef char value_type; ++ typedef int* pointer; ++}; ++ ++int main() ++{ ++ BOOST_TEST_TRAIT_TRUE((boost::core::is_same::type>)); ++ BOOST_TEST_TRAIT_TRUE((boost::core::is_same::type>)); ++ return boost::report_errors(); ++} +diff --git a/test/allocator_rebind_test.cpp b/test/allocator_rebind_test.cpp +new file mode 100644 +index 0000000..5e4030f +--- /dev/null ++++ b/boost/libs/core/test/allocator_rebind_test.cpp +@@ -0,0 +1,30 @@ ++/* ++Copyright 2020 Glen Joseph Fernandes ++(glenjofe@gmail.com) ++ ++Distributed under the Boost Software License, Version 1.0. ++(http://www.boost.org/LICENSE_1_0.txt) ++*/ ++#include ++#include ++#include ++ ++template ++struct A1 { }; ++ ++template ++struct A2 { ++ template ++ struct rebind { ++ typedef A1 other; ++ }; ++}; ++ ++int main() ++{ ++ BOOST_TEST_TRAIT_TRUE((boost::core::is_same, ++ boost::allocator_rebind, bool>::type>)); ++ BOOST_TEST_TRAIT_TRUE((boost::core::is_same, ++ boost::allocator_rebind, bool>::type>)); ++ return boost::report_errors(); ++} +diff --git a/test/allocator_size_type_test.cpp b/test/allocator_size_type_test.cpp +new file mode 100644 +index 0000000..bdc8dc5 +--- /dev/null ++++ b/boost/libs/core/test/allocator_size_type_test.cpp +@@ -0,0 +1,34 @@ ++/* ++Copyright 2020 Glen Joseph Fernandes ++(glenjofe@gmail.com) ++ ++Distributed under the Boost Software License, Version 1.0. ++(http://www.boost.org/LICENSE_1_0.txt) ++*/ ++#include ++#include ++#include ++ ++#if !defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS) ++struct A1 { ++ typedef long difference_type; ++}; ++#else ++struct A1 { ++ typedef unsigned long size_type; ++}; ++#endif ++ ++struct A2 { ++ typedef long difference_type; ++ typedef unsigned short size_type; ++}; ++ ++int main() ++{ ++ BOOST_TEST_TRAIT_TRUE((boost::core::is_same::type>)); ++ BOOST_TEST_TRAIT_TRUE((boost::core::is_same::type>)); ++ return boost::report_errors(); ++} +diff --git a/test/allocator_soccc_test.cpp b/test/allocator_soccc_test.cpp +new file mode 100644 +index 0000000..d361549 +--- /dev/null ++++ b/boost/libs/core/test/allocator_soccc_test.cpp +@@ -0,0 +1,40 @@ ++/* ++Copyright 2020 Glen Joseph Fernandes ++(glenjofe@gmail.com) ++ ++Distributed under the Boost Software License, Version 1.0. ++(http://www.boost.org/LICENSE_1_0.txt) ++*/ ++#include ++#include ++ ++struct A1 { ++ A1(int v) ++ : value(v) { } ++ ++ int value; ++}; ++ ++#if defined(BOOST_CORE_ALLOCATOR_DETECTION) ++struct A2 { ++ A2(int v) ++ : value(v) { } ++ ++ A2 select_on_container_copy_construction() const { ++ return A2(value + 1); ++ } ++ ++ int value; ++}; ++#endif ++ ++int main() ++{ ++ BOOST_TEST_EQ(1, ++ boost::allocator_select_on_container_copy_construction(A1(1)).value); ++#if defined(BOOST_CORE_ALLOCATOR_DETECTION) ++ BOOST_TEST_EQ(2, ++ boost::allocator_select_on_container_copy_construction(A2(1)).value); ++#endif ++ return boost::report_errors(); ++} +diff --git a/test/allocator_value_type_test.cpp b/test/allocator_value_type_test.cpp +new file mode 100644 +index 0000000..ddd5601 +--- /dev/null ++++ b/boost/libs/core/test/allocator_value_type_test.cpp +@@ -0,0 +1,21 @@ ++/* ++Copyright 2020 Glen Joseph Fernandes ++(glenjofe@gmail.com) ++ ++Distributed under the Boost Software License, Version 1.0. ++(http://www.boost.org/LICENSE_1_0.txt) ++*/ ++#include ++#include ++#include ++ ++struct A { ++ typedef int value_type; ++}; ++ ++int main() ++{ ++ BOOST_TEST_TRAIT_TRUE((boost::core::is_same::type>)); ++ return boost::report_errors(); ++} +diff --git a/test/allocator_void_pointer_test.cpp b/test/allocator_void_pointer_test.cpp +new file mode 100644 +index 0000000..2ec053b +--- /dev/null ++++ b/boost/libs/core/test/allocator_void_pointer_test.cpp +@@ -0,0 +1,28 @@ ++/* ++Copyright 2020 Glen Joseph Fernandes ++(glenjofe@gmail.com) ++ ++Distributed under the Boost Software License, Version 1.0. ++(http://www.boost.org/LICENSE_1_0.txt) ++*/ ++#include ++#include ++#include ++ ++struct A1 { ++ typedef int* pointer; ++}; ++ ++struct A2 { ++ typedef int* pointer; ++ typedef bool* void_pointer; ++}; ++ ++int main() ++{ ++ BOOST_TEST_TRAIT_TRUE((boost::core::is_same::type>)); ++ BOOST_TEST_TRAIT_TRUE((boost::core::is_same::type>)); ++ return boost::report_errors(); ++} diff --git a/boost.spec b/boost.spec index 0ee76f2..b13a2cf 100644 --- a/boost.spec +++ b/boost.spec @@ -1,3 +1,4 @@ +%define anolis_release .0.1 # Support for documentation installation As the %%doc macro erases the # target directory ($RPM_BUILD_ROOT%%{_docdir}/%%{name}), manually # installed documentation must be saved into a temporary dedicated @@ -27,7 +28,7 @@ Name: boost Summary: The free peer-reviewed portable C++ source libraries Version: 1.66.0 %global version_enc 1_66_0 -Release: 10%{?dist} +Release: 10%{anolis_release}%{?dist} License: Boost and MIT and Python %global toplev_dirname %{name}_%{version_enc} @@ -143,6 +144,21 @@ Patch90: boost-1.66-build-memory-leak.patch # https://github.com/boostorg/graph/pull/84 Patch91: boost-1.66-graph-return-local-addr.patch +# Begin Anolis customized patches +# backport patches from upstream +Patch1001: 1001-Replace-std::allocate-with-std::allocator_traits.patch +Patch1002: 1002-Replace-std::allocate-deprecated-in-C++17.patch + +Patch1003: 1003-Implement-empty_value.patch +Patch1004: 1004-Make-empty_value-trivial-if-T-is-trivial.patch +Patch1005: 1005-Add-documentation-for-empty_value.patch +Patch1006: 1006-Name-the-empty_value-template-parameters.patch + +Patch1007: 1007-Improve-C++11-allocator-support.patch +Patch1008: 1008-Use-boost::allocator_rebind-instead-of-A::template-rebind.patch +Patch1009: 1009-Implement-allocator-access-utilities.patch +# End Anolis customized patches + %bcond_with tests %bcond_with docs_generated @@ -650,6 +666,15 @@ find ./boost -name '*.hpp' -perm /111 | xargs chmod a-x %patch89 -p1 %patch90 -p1 %patch91 -p2 +%patch1001 -p2 +%patch1002 -p2 +%patch1003 -p2 +%patch1004 -p2 +%patch1005 -p2 +%patch1006 -p2 +%patch1007 -p2 +%patch1008 -p2 +%patch1009 -p2 %build PYTHON3_ABIFLAGS=$(/usr/bin/python3-config --abiflags) @@ -1309,6 +1334,18 @@ fi %{_mandir}/man1/bjam.1* %changelog +* Fri Jan 1 2021 Liwei Ge - 1.66.0-10.0.1 +- backport patches to fit with C++20 until upstream chase up: + * Replace-std::allocate-with-std::allocator_traits.patch + * Replace-std::allocate-deprecated-in-C++17.patch + * Implement-empty_value.patch + * Make-empty_value-trivial-if-T-is-trivial.patch + * Add-documentation-for-empty_value.patch + * Name-the-empty_value-template-parameters.patch + * Improve-C++11-allocator-support.patch + * Use-boost::allocator_rebind-instead-of-A::template-rebind.patch + * Implement-allocator-access-utilities.patch + * Tue Aug 04 2020 Jonathan Wakely - 1.66.0-10 - Revert changes for s390x support in Boost.Context -- Gitee