Added C++17's is_always_equal to allocator_traits and scoped_allocator_adaptor

This commit is contained in:
Ion Gaztañaga
2015-01-18 11:22:52 +01:00
parent 1012987897
commit f0f35a830d
6 changed files with 113 additions and 60 deletions

View File

@@ -749,7 +749,8 @@ C++11 further improves stateful allocator support through
an allocator writer can customize its behaviour (should the container propagate it in
move constructor, swap, etc.?) following `allocator_traits` requirements. [*Boost.Container]
not only supports this model with C++11 but also [*backports it to C++03] via
[classref boost::container::allocator_traits boost::container::allocator_traits]. This class
[classref boost::container::allocator_traits boost::container::allocator_traits] including some
C++17 changes. This class
offers some workarounds for C++03 compilers to achieve the same allocator guarantees as
`std::allocator_traits`.
@@ -1084,6 +1085,7 @@ use [*Boost.Container]? There are several reasons for that:
* Massive dependency reorganization. Now [*Boost.Container depends on very basic utilities like Boost.Core
and [*Boost.Intrusive]. Preprocessed code size have decreased considerably and compilation times have improved.
* Added `nth` and `index_of` functions to containers with random-access iterators (except `basic_string`).
* Added C++17's `allocator_traits<Allocator>::is_always_equal`.
* Fixed bugs:
* [@https://svn.boost.org/trac/boost/ticket/10790 Trac #10790 (['long long errors from container"])].
* [@https://svn.boost.org/trac/boost/ticket/10808 Trac #10808 (['compare equal operator of vector is broken"])].

View File

@@ -26,6 +26,7 @@
// container
#include <boost/container/container_fwd.hpp>
#include <boost/container/detail/mpl.hpp>
#include <boost/container/detail/type_traits.hpp> //is_empty
#include <boost/container/detail/placement_new.hpp>
#ifndef BOOST_CONTAINER_DETAIL_STD_FWD_HPP
#include <boost/container/detail/std_fwd.hpp>
@@ -94,6 +95,7 @@ BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(size_type)
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(propagate_on_container_copy_assignment)
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(propagate_on_container_move_assignment)
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(propagate_on_container_swap)
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(is_always_equal)
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(difference_type)
} //namespace container_detail {
@@ -138,12 +140,15 @@ struct allocator_traits
//! Allocator::propagate_on_container_copy_assignment if such a type exists, otherwise a type
//! with an internal constant static boolean member <code>value</code> == false.
typedef see_documentation propagate_on_container_copy_assignment;
//! Allocator::propagate_on_container_move_assignment if such a type exists, otherwise otherwise a type
//! Allocator::propagate_on_container_move_assignment if such a type exists, otherwise a type
//! with an internal constant static boolean member <code>value</code> == false.
typedef see_documentation propagate_on_container_move_assignment;
//! Allocator::propagate_on_container_swap if such a type exists, otherwise an otherwise a type
//! Allocator::propagate_on_container_swap if such a type exists, otherwise a type
//! with an internal constant static boolean member <code>value</code> == false.
typedef see_documentation propagate_on_container_swap;
//! Allocator::is_always_equal if such a type exists, otherwise a type
//! with an internal constant static boolean member <code>value</code> == is_empty<Allocator>::value
typedef see_documentation is_always_equal;
//! Defines an allocator: Allocator::rebind<T>::other if such a type exists; otherwise, Allocator<T, Args>
//! if Allocator is a class template instantiation of the form Allocator<U, Args>, where Args is zero or
//! more type arguments ; otherwise, the instantiation of rebind_alloc is ill-formed.
@@ -210,7 +215,10 @@ struct allocator_traits
typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Allocator,
propagate_on_container_swap, container_detail::false_type)
propagate_on_container_swap;
//is_always_equal
typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Allocator,
is_always_equal, container_detail::is_empty<Allocator>)
is_always_equal;
#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
//C++11
template <typename T> using rebind_alloc = typename boost::intrusive::pointer_rebind<Allocator, T>::type;

View File

@@ -38,6 +38,7 @@ using ::boost::move_detail::is_floating_point;
using ::boost::move_detail::is_integral;
using ::boost::move_detail::is_enum;
using ::boost::move_detail::is_pod;
using ::boost::move_detail::is_empty;
using ::boost::move_detail::is_trivially_destructible;
using ::boost::move_detail::is_trivially_default_constructible;
using ::boost::move_detail::is_trivially_copy_constructible;

View File

@@ -474,6 +474,10 @@ class scoped_allocator_adaptor_base
outer_traits_type::propagate_on_container_swap::value ||
inner_allocator_type::propagate_on_container_swap::value
> propagate_on_container_swap;
typedef container_detail::bool_<
outer_traits_type::is_always_equal::value &&
inner_allocator_type::is_always_equal::value
> is_always_equal;
scoped_allocator_adaptor_base()
{}
@@ -613,6 +617,11 @@ class scoped_allocator_adaptor_base<OuterAlloc, true, BOOST_MOVE_TARG##N>\
inner_allocator_type::propagate_on_container_swap::value\
> propagate_on_container_swap;\
\
typedef container_detail::bool_<\
outer_traits_type::is_always_equal::value &&\
inner_allocator_type::is_always_equal::value\
> is_always_equal;\
\
scoped_allocator_adaptor_base(){}\
\
template <class OuterA2>\
@@ -746,6 +755,8 @@ class scoped_allocator_adaptor_base< OuterAlloc BOOST_CONTAINER_SCOPEDALLOC_DUMM
propagate_on_container_move_assignment propagate_on_container_move_assignment;
typedef typename outer_traits_type::
propagate_on_container_swap propagate_on_container_swap;
typedef typename outer_traits_type::
is_always_equal is_always_equal;
scoped_allocator_adaptor_base()
{}
@@ -913,21 +924,27 @@ class scoped_allocator_adaptor
typedef typename outer_traits_type::const_void_pointer const_void_pointer;
//! Type: A type with a constant boolean <code>value</code> == true if
//!<code>allocator_traits<Allocator>::propagate_on_container_copy_assignment::value</code> is
//! true for any <code>Allocator</code> in the set of <code>OuterAlloc</code> and <code>InnerAllocs...</code>; otherwise, false otherwise.
//! true for any <code>Allocator</code> in the set of <code>OuterAlloc</code> and <code>InnerAllocs...</code>, false otherwise.
typedef typename base_type::
propagate_on_container_copy_assignment propagate_on_container_copy_assignment;
//! Type: A type with a constant boolean <code>value</code> == true if
//!<code>allocator_traits<Allocator>::propagate_on_container_move_assignment::value</code> is
//! true for any <code>Allocator</code> in the set of <code>OuterAlloc</code> and <code>InnerAllocs...</code>; otherwise, false otherwise.
//! true for any <code>Allocator</code> in the set of <code>OuterAlloc</code> and <code>InnerAllocs...</code>, false otherwise.
typedef typename base_type::
propagate_on_container_move_assignment propagate_on_container_move_assignment;
//! Type: A type with a constant boolean <code>value</code> == true if
//!<code>allocator_traits<Allocator>::propagate_on_container_swap::value</code> is
//! true for any <code>Allocator</code> in the set of <code>OuterAlloc</code> and <code>InnerAllocs...</code>; otherwise, false otherwise.
//! true for any <code>Allocator</code> in the set of <code>OuterAlloc</code> and <code>InnerAllocs...</code>, false otherwise.
typedef typename base_type::
propagate_on_container_swap propagate_on_container_swap;
//! Type: A type with a constant boolean <code>value</code> == true if
//!<code>allocator_traits<Allocator>::is_always_equal::value</code> is
//! true for all <code>Allocator</code> in the set of <code>OuterAlloc</code> and <code>InnerAllocs...</code>, false otherwise.
typedef typename base_type::
is_always_equal is_always_equal;
//! Type: Rebinds scoped allocator to
//! <code>typedef scoped_allocator_adaptor
//! < typename outer_traits_type::template portable_rebind_alloc<U>::type

View File

@@ -103,6 +103,8 @@ class ComplexAllocator
true_type propagate_on_container_move_assignment;
typedef boost::container::container_detail::
true_type propagate_on_container_swap;
typedef boost::container::container_detail::
true_type is_always_equal;
ComplexAllocator()
: allocate_called_(false)
@@ -247,6 +249,8 @@ int main()
< SimpleAllocator<int> >::propagate_on_container_move_assignment::value == false ));
BOOST_STATIC_ASSERT(( boost::container::allocator_traits
< SimpleAllocator<int> >::propagate_on_container_swap::value == false ));
BOOST_STATIC_ASSERT(( boost::container::allocator_traits
< SimpleAllocator<int> >::is_always_equal::value == false ));
BOOST_STATIC_ASSERT(( is_same<boost::container::allocator_traits
< SimpleAllocator<int> >::rebind_traits<double>::allocator_type
, SimpleAllocator<double> >::value ));
@@ -275,6 +279,8 @@ int main()
< ComplexAllocator<int> >::propagate_on_container_move_assignment::value == true ));
BOOST_STATIC_ASSERT(( boost::container::allocator_traits
< ComplexAllocator<int> >::propagate_on_container_swap::value == true ));
BOOST_STATIC_ASSERT(( boost::container::allocator_traits
< ComplexAllocator<int> >::is_always_equal::value == true ));
BOOST_STATIC_ASSERT(( is_same<boost::container::allocator_traits
< ComplexAllocator<int> >::rebind_traits<double>::allocator_type
, ComplexAllocator<double> >::value ));

View File

@@ -21,7 +21,7 @@
using namespace boost::container;
template<class T, unsigned int Id, bool Propagate = false>
template<class T, unsigned int Id, bool HasTrueTypes = false>
class test_allocator
{
BOOST_COPYABLE_AND_MOVABLE(test_allocator)
@@ -30,12 +30,13 @@ class test_allocator
template<class U>
struct rebind
{
typedef test_allocator<U, Id, Propagate> other;
typedef test_allocator<U, Id, HasTrueTypes> other;
};
typedef container_detail::bool_<Propagate> propagate_on_container_copy_assignment;
typedef container_detail::bool_<Propagate> propagate_on_container_move_assignment;
typedef container_detail::bool_<Propagate> propagate_on_container_swap;
typedef container_detail::bool_<HasTrueTypes> propagate_on_container_copy_assignment;
typedef container_detail::bool_<HasTrueTypes> propagate_on_container_move_assignment;
typedef container_detail::bool_<HasTrueTypes> propagate_on_container_swap;
typedef container_detail::bool_<HasTrueTypes> is_always_equal;
typedef T value_type;
test_allocator()
@@ -51,12 +52,12 @@ class test_allocator
{}
template<class U>
test_allocator(BOOST_RV_REF_BEG test_allocator<U, Id, Propagate> BOOST_RV_REF_END)
test_allocator(BOOST_RV_REF_BEG test_allocator<U, Id, HasTrueTypes> BOOST_RV_REF_END)
: m_move_contructed(true), m_move_assigned(false)
{}
template<class U>
test_allocator(const test_allocator<U, Id, Propagate> &)
test_allocator(const test_allocator<U, Id, HasTrueTypes> &)
{}
test_allocator & operator=(BOOST_COPY_ASSIGN_REF(test_allocator))
@@ -83,14 +84,14 @@ class test_allocator
bool m_move_assigned;
};
template <class T1, class T2, unsigned int Id, bool Propagate>
bool operator==( const test_allocator<T1, Id, Propagate>&
, const test_allocator<T2, Id, Propagate>&)
template <class T1, class T2, unsigned int Id, bool HasTrueTypes>
bool operator==( const test_allocator<T1, Id, HasTrueTypes>&
, const test_allocator<T2, Id, HasTrueTypes>&)
{ return true; }
template <class T1, class T2, unsigned int Id, bool Propagate>
bool operator!=( const test_allocator<T1, Id, Propagate>&
, const test_allocator<T2, Id, Propagate>&)
template <class T1, class T2, unsigned int Id, bool HasTrueTypes>
bool operator!=( const test_allocator<T1, Id, HasTrueTypes>&
, const test_allocator<T2, Id, HasTrueTypes>&)
{ return false; }
@@ -269,12 +270,12 @@ int main()
typedef test_allocator<tagged_integer<2>, 2> InnerAlloc2;
typedef test_allocator<tagged_integer<1>, 11> Inner11IdAlloc1;
typedef test_allocator<tagged_integer<0>, 0, false> OuterAllocFalsePropagate;
typedef test_allocator<tagged_integer<0>, 0, true> OuterAllocTruePropagate;
typedef test_allocator<tagged_integer<1>, 1, false> InnerAlloc1FalsePropagate;
typedef test_allocator<tagged_integer<1>, 1, true> InnerAlloc1TruePropagate;
typedef test_allocator<tagged_integer<2>, 2, false> InnerAlloc2FalsePropagate;
typedef test_allocator<tagged_integer<2>, 2, true> InnerAlloc2TruePropagate;
typedef test_allocator<tagged_integer<0>, 0, false> OuterAllocFalseHasTrueTypes;
typedef test_allocator<tagged_integer<0>, 0, true> OuterAllocTrueHasTrueTypes;
typedef test_allocator<tagged_integer<1>, 1, false> InnerAlloc1FalseHasTrueTypes;
typedef test_allocator<tagged_integer<1>, 1, true> InnerAlloc1TrueHasTrueTypes;
typedef test_allocator<tagged_integer<2>, 2, false> InnerAlloc2FalseHasTrueTypes;
typedef test_allocator<tagged_integer<2>, 2, true> InnerAlloc2TrueHasTrueTypes;
//
typedef scoped_allocator_adaptor< OuterAlloc > Scoped0Inner;
@@ -379,40 +380,40 @@ int main()
{
//Propagation test
typedef scoped_allocator_adaptor< OuterAllocFalsePropagate > Scoped0InnerF;
typedef scoped_allocator_adaptor< OuterAllocTruePropagate > Scoped0InnerT;
typedef scoped_allocator_adaptor< OuterAllocFalsePropagate
, InnerAlloc1FalsePropagate > Scoped1InnerFF;
typedef scoped_allocator_adaptor< OuterAllocFalsePropagate
, InnerAlloc1TruePropagate > Scoped1InnerFT;
typedef scoped_allocator_adaptor< OuterAllocTruePropagate
, InnerAlloc1FalsePropagate > Scoped1InnerTF;
typedef scoped_allocator_adaptor< OuterAllocTruePropagate
, InnerAlloc1TruePropagate > Scoped1InnerTT;
typedef scoped_allocator_adaptor< OuterAllocFalsePropagate
, InnerAlloc1FalsePropagate
, InnerAlloc2FalsePropagate > Scoped2InnerFFF;
typedef scoped_allocator_adaptor< OuterAllocFalsePropagate
, InnerAlloc1FalsePropagate
, InnerAlloc2TruePropagate > Scoped2InnerFFT;
typedef scoped_allocator_adaptor< OuterAllocFalsePropagate
, InnerAlloc1TruePropagate
, InnerAlloc2FalsePropagate > Scoped2InnerFTF;
typedef scoped_allocator_adaptor< OuterAllocFalsePropagate
, InnerAlloc1TruePropagate
, InnerAlloc2TruePropagate > Scoped2InnerFTT;
typedef scoped_allocator_adaptor< OuterAllocTruePropagate
, InnerAlloc1FalsePropagate
, InnerAlloc2FalsePropagate > Scoped2InnerTFF;
typedef scoped_allocator_adaptor< OuterAllocTruePropagate
, InnerAlloc1FalsePropagate
, InnerAlloc2TruePropagate > Scoped2InnerTFT;
typedef scoped_allocator_adaptor< OuterAllocTruePropagate
, InnerAlloc1TruePropagate
, InnerAlloc2FalsePropagate > Scoped2InnerTTF;
typedef scoped_allocator_adaptor< OuterAllocTruePropagate
, InnerAlloc1TruePropagate
, InnerAlloc2TruePropagate > Scoped2InnerTTT;
typedef scoped_allocator_adaptor< OuterAllocFalseHasTrueTypes > Scoped0InnerF;
typedef scoped_allocator_adaptor< OuterAllocTrueHasTrueTypes > Scoped0InnerT;
typedef scoped_allocator_adaptor< OuterAllocFalseHasTrueTypes
, InnerAlloc1FalseHasTrueTypes > Scoped1InnerFF;
typedef scoped_allocator_adaptor< OuterAllocFalseHasTrueTypes
, InnerAlloc1TrueHasTrueTypes > Scoped1InnerFT;
typedef scoped_allocator_adaptor< OuterAllocTrueHasTrueTypes
, InnerAlloc1FalseHasTrueTypes > Scoped1InnerTF;
typedef scoped_allocator_adaptor< OuterAllocTrueHasTrueTypes
, InnerAlloc1TrueHasTrueTypes > Scoped1InnerTT;
typedef scoped_allocator_adaptor< OuterAllocFalseHasTrueTypes
, InnerAlloc1FalseHasTrueTypes
, InnerAlloc2FalseHasTrueTypes > Scoped2InnerFFF;
typedef scoped_allocator_adaptor< OuterAllocFalseHasTrueTypes
, InnerAlloc1FalseHasTrueTypes
, InnerAlloc2TrueHasTrueTypes > Scoped2InnerFFT;
typedef scoped_allocator_adaptor< OuterAllocFalseHasTrueTypes
, InnerAlloc1TrueHasTrueTypes
, InnerAlloc2FalseHasTrueTypes > Scoped2InnerFTF;
typedef scoped_allocator_adaptor< OuterAllocFalseHasTrueTypes
, InnerAlloc1TrueHasTrueTypes
, InnerAlloc2TrueHasTrueTypes > Scoped2InnerFTT;
typedef scoped_allocator_adaptor< OuterAllocTrueHasTrueTypes
, InnerAlloc1FalseHasTrueTypes
, InnerAlloc2FalseHasTrueTypes > Scoped2InnerTFF;
typedef scoped_allocator_adaptor< OuterAllocTrueHasTrueTypes
, InnerAlloc1FalseHasTrueTypes
, InnerAlloc2TrueHasTrueTypes > Scoped2InnerTFT;
typedef scoped_allocator_adaptor< OuterAllocTrueHasTrueTypes
, InnerAlloc1TrueHasTrueTypes
, InnerAlloc2FalseHasTrueTypes > Scoped2InnerTTF;
typedef scoped_allocator_adaptor< OuterAllocTrueHasTrueTypes
, InnerAlloc1TrueHasTrueTypes
, InnerAlloc2TrueHasTrueTypes > Scoped2InnerTTT;
//propagate_on_container_copy_assignment
//0 inner
@@ -470,6 +471,24 @@ int main()
BOOST_STATIC_ASSERT(( Scoped2InnerTFT::propagate_on_container_swap::value ));
BOOST_STATIC_ASSERT(( Scoped2InnerTTF::propagate_on_container_swap::value ));
BOOST_STATIC_ASSERT(( Scoped2InnerTTT::propagate_on_container_swap::value ));
//is_always_equal
//0 inner
BOOST_STATIC_ASSERT(( !Scoped0InnerF::is_always_equal::value ));
BOOST_STATIC_ASSERT(( Scoped0InnerT::is_always_equal::value ));
//1 inner
BOOST_STATIC_ASSERT(( !Scoped1InnerFF::is_always_equal::value ));
BOOST_STATIC_ASSERT(( !Scoped1InnerFT::is_always_equal::value ));
BOOST_STATIC_ASSERT(( !Scoped1InnerTF::is_always_equal::value ));
BOOST_STATIC_ASSERT(( Scoped1InnerTT::is_always_equal::value ));
//2 inner
BOOST_STATIC_ASSERT(( !Scoped2InnerFFF::is_always_equal::value ));
BOOST_STATIC_ASSERT(( !Scoped2InnerFFT::is_always_equal::value ));
BOOST_STATIC_ASSERT(( !Scoped2InnerFTF::is_always_equal::value ));
BOOST_STATIC_ASSERT(( !Scoped2InnerFTT::is_always_equal::value ));
BOOST_STATIC_ASSERT(( !Scoped2InnerTFF::is_always_equal::value ));
BOOST_STATIC_ASSERT(( !Scoped2InnerTFT::is_always_equal::value ));
BOOST_STATIC_ASSERT(( !Scoped2InnerTTF::is_always_equal::value ));
BOOST_STATIC_ASSERT(( Scoped2InnerTTT::is_always_equal::value ));
}
//Default constructor