Fix Trac #12117 ("flat_set constructor with ordered_unique_range") adding checks to constructors in debug mode

Fix typos on value_type checks in flat_[multi]map.
This commit is contained in:
Ion Gaztañaga
2016-08-15 23:22:57 +02:00
parent 324130703e
commit fb1be6fa75
6 changed files with 122 additions and 33 deletions

View File

@@ -1219,6 +1219,7 @@ use [*Boost.Container]? There are several reasons for that:
* [@https://svn.boost.org/trac/boost/ticket/9481 Trac #9481: ['"Minor comment typo in Boost.Container"]].
* [@https://svn.boost.org/trac/boost/ticket/11170 Trac #11170: ['"Doc slip for index_of"]].
* [@https://svn.boost.org/trac/boost/ticket/11802 Trac #11802: ['"Incorrect ordering after using insert() with ordered_range_t on a flat_multiset with a non-default sort order"]].
* [@https://svn.boost.org/trac/boost/ticket/12117 Trac #12117: ['"flat_set constructor with ordered_unique_range"]].
* [@https://svn.boost.org/trac/boost/ticket/12177 Trac #12177: ['"vector::priv_merge uses unqualified uintptr_t"]].
* [@https://svn.boost.org/trac/boost/ticket/12183 Trac #12183: ['"GCC 6.1 thinks boost::container::string violates strict aliasing"]].
* [@https://svn.boost.org/trac/boost/ticket/12256 Trac #12256: ['"set<std::pair<int,int>>::insert cause compilation error in debug configuration in Visual Studio 2012"]].

View File

@@ -32,6 +32,7 @@
#include <boost/container/detail/destroyers.hpp>
#include <boost/container/detail/algorithm.hpp> //algo_equal(), algo_lexicographical_compare
#include <boost/container/detail/iterator.hpp>
#include <boost/container/detail/is_sorted.hpp>
#include <boost/container/allocator_traits.hpp>
#ifdef BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER
#include <boost/intrusive/pointer_traits.hpp>
@@ -238,7 +239,20 @@ class flat_tree
, const Compare& comp = Compare()
, const allocator_type& a = allocator_type())
: m_data(comp, a)
{ this->m_data.m_vect.insert(this->m_data.m_vect.end(), first, last); }
{
this->m_data.m_vect.insert(this->m_data.m_vect.end(), first, last);
BOOST_ASSERT((is_sorted)(this->m_data.m_vect.cbegin(), this->m_data.m_vect.cend(), this->priv_value_comp()));
}
template <class InputIterator>
flat_tree( ordered_unique_range_t, InputIterator first, InputIterator last
, const Compare& comp = Compare()
, const allocator_type& a = allocator_type())
: m_data(comp, a)
{
this->m_data.m_vect.insert(this->m_data.m_vect.end(), first, last);
BOOST_ASSERT((is_sorted_and_unique)(this->m_data.m_vect.cbegin(), this->m_data.m_vect.cend(), this->priv_value_comp()));
}
template <class InputIterator>
flat_tree( bool unique_insertion
@@ -275,6 +289,12 @@ class flat_tree
boost::container::container_detail::is_nothrow_move_assignable<Compare>::value)
{ m_data = boost::move(x.m_data); return *this; }
BOOST_CONTAINER_FORCEINLINE const value_compare &priv_value_comp() const
{ return static_cast<const value_compare &>(this->m_data); }
BOOST_CONTAINER_FORCEINLINE value_compare &priv_value_comp()
{ return static_cast<value_compare &>(this->m_data); }
public:
// accessors:
Compare key_comp() const

View File

@@ -0,0 +1,57 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2016-2016. 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)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_DETAIL_IS_SORTED_HPP
#define BOOST_CONTAINER_DETAIL_IS_SORTED_HPP
#ifndef BOOST_CONFIG_HPP
# include <boost/config.hpp>
#endif
#if defined(BOOST_HAS_PRAGMA_ONCE)
# pragma once
#endif
namespace boost {
namespace container {
namespace container_detail {
template <class ForwardIterator, class Pred>
bool is_sorted (ForwardIterator first, ForwardIterator last, Pred pred)
{
if(first != last){
ForwardIterator next = first;
while (++next != last){
if(pred(*next, *first))
return false;
++first;
}
}
return true;
}
template <class ForwardIterator, class Pred>
bool is_sorted_and_unique (ForwardIterator first, ForwardIterator last, Pred pred)
{
if(first != last){
ForwardIterator next = first;
while (++next != last){
if(!pred(*first, *next))
return false;
++first;
}
}
return true;
}
} //namespace container_detail {
} //namespace container {
} //namespace boost {
#endif //#ifndef BOOST_CONTAINER_DETAIL_IS_SORTED_HPP

View File

@@ -187,7 +187,7 @@ class flat_map
container_detail::is_nothrow_default_constructible<Compare>::value)
: m_flat_tree()
{
//A type must be std::pair<Key, T>
//value_type must be std::pair<Key, T>
BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
}
@@ -198,7 +198,7 @@ class flat_map
explicit flat_map(const Compare& comp, const allocator_type& a = allocator_type())
: m_flat_tree(comp, container_detail::force<impl_allocator_type>(a))
{
//A type must be std::pair<Key, T>
//value_type must be std::pair<Key, T>
BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
}
@@ -208,7 +208,7 @@ class flat_map
explicit flat_map(const allocator_type& a)
: m_flat_tree(container_detail::force<impl_allocator_type>(a))
{
//A type must be std::pair<Key, T>
//value_type must be std::pair<Key, T>
BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
}
@@ -222,7 +222,7 @@ class flat_map
const allocator_type& a = allocator_type())
: m_flat_tree(true, first, last, comp, container_detail::force<impl_allocator_type>(a))
{
//A type must be std::pair<Key, T>
//value_type must be std::pair<Key, T>
BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
}
@@ -235,7 +235,7 @@ class flat_map
flat_map(InputIterator first, InputIterator last, const allocator_type& a)
: m_flat_tree(true, first, last, Compare(), container_detail::force<impl_allocator_type>(a))
{
//A type must be std::pair<Key, T>
//value_type must be std::pair<Key, T>
BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
}
@@ -252,9 +252,9 @@ class flat_map
template <class InputIterator>
flat_map( ordered_unique_range_t, InputIterator first, InputIterator last
, const Compare& comp = Compare(), const allocator_type& a = allocator_type())
: m_flat_tree(ordered_range, first, last, comp, a)
: m_flat_tree(ordered_unique_range, first, last, comp, a)
{
//A type must be std::pair<Key, T>
//value_type must be std::pair<Key, T>
BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
}
@@ -268,7 +268,7 @@ class flat_map
const allocator_type& a = allocator_type())
: m_flat_tree(true, il.begin(), il.end(), comp, container_detail::force<impl_allocator_type>(a))
{
//A type must be std::pair<Key, T>
//value_type must be std::pair<Key, T>
BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
}
@@ -280,7 +280,7 @@ class flat_map
flat_map(std::initializer_list<value_type> il, const allocator_type& a)
: m_flat_tree(true, il.begin(), il.end(), Compare(), container_detail::force<impl_allocator_type>(a))
{
//A type must be std::pair<Key, T>
//value_type must be std::pair<Key, T>
BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
}
@@ -296,9 +296,9 @@ class flat_map
//! <b>Note</b>: Non-standard extension.
flat_map(ordered_unique_range_t, std::initializer_list<value_type> il, const Compare& comp = Compare(),
const allocator_type& a = allocator_type())
: m_flat_tree(ordered_range, il.begin(), il.end(), comp, a)
: m_flat_tree(ordered_unique_range, il.begin(), il.end(), comp, a)
{
//A type must be std::pair<Key, T>
//value_type must be std::pair<Key, T>
BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
}
#endif
@@ -309,7 +309,7 @@ class flat_map
flat_map(const flat_map& x)
: m_flat_tree(x.m_flat_tree)
{
//A type must be std::pair<Key, T>
//value_type must be std::pair<Key, T>
BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
}
@@ -323,7 +323,7 @@ class flat_map
BOOST_NOEXCEPT_IF(boost::container::container_detail::is_nothrow_move_constructible<Compare>::value)
: m_flat_tree(boost::move(x.m_flat_tree))
{
//A type must be std::pair<Key, T>
//value_type must be std::pair<Key, T>
BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
}
@@ -333,7 +333,7 @@ class flat_map
flat_map(const flat_map& x, const allocator_type &a)
: m_flat_tree(x.m_flat_tree, a)
{
//A type must be std::pair<Key, T>
//value_type must be std::pair<Key, T>
BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
}
@@ -344,7 +344,7 @@ class flat_map
flat_map(BOOST_RV_REF(flat_map) x, const allocator_type &a)
: m_flat_tree(boost::move(x.m_flat_tree), a)
{
//A type must be std::pair<Key, T>
//value_type must be std::pair<Key, T>
BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
}
@@ -1215,7 +1215,7 @@ class flat_multimap
container_detail::is_nothrow_default_constructible<Compare>::value)
: m_flat_tree()
{
//A type must be std::pair<Key, T>
//value_type must be std::pair<Key, T>
BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
}
@@ -1227,7 +1227,7 @@ class flat_multimap
const allocator_type& a = allocator_type())
: m_flat_tree(comp, container_detail::force<impl_allocator_type>(a))
{
//A type must be std::pair<Key, T>
//value_type must be std::pair<Key, T>
BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
}
@@ -1237,7 +1237,7 @@ class flat_multimap
explicit flat_multimap(const allocator_type& a)
: m_flat_tree(container_detail::force<impl_allocator_type>(a))
{
//A type must be std::pair<Key, T>
//value_type must be std::pair<Key, T>
BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
}
@@ -1252,7 +1252,7 @@ class flat_multimap
const allocator_type& a = allocator_type())
: m_flat_tree(false, first, last, comp, container_detail::force<impl_allocator_type>(a))
{
//A type must be std::pair<Key, T>
//value_type must be std::pair<Key, T>
BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
}
@@ -1265,7 +1265,7 @@ class flat_multimap
flat_multimap(InputIterator first, InputIterator last, const allocator_type& a)
: m_flat_tree(false, first, last, Compare(), container_detail::force<impl_allocator_type>(a))
{
//A type must be std::pair<Key, T>
//value_type must be std::pair<Key, T>
BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
}
@@ -1284,7 +1284,7 @@ class flat_multimap
const allocator_type& a = allocator_type())
: m_flat_tree(ordered_range, first, last, comp, a)
{
//A type must be std::pair<Key, T>
//value_type must be std::pair<Key, T>
BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
}
@@ -1297,7 +1297,7 @@ class flat_multimap
flat_multimap(std::initializer_list<value_type> il, const Compare& comp = Compare(), const allocator_type& a = allocator_type())
: m_flat_tree(false, il.begin(), il.end(), comp, container_detail::force<impl_allocator_type>(a))
{
//A type must be std::pair<Key, T>
//value_type must be std::pair<Key, T>
BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
}
@@ -1309,7 +1309,7 @@ class flat_multimap
flat_multimap(std::initializer_list<value_type> il, const allocator_type& a)
: m_flat_tree(false, il.begin(), il.end(), Compare(), container_detail::force<impl_allocator_type>(a))
{
//A type must be std::pair<Key, T>
//value_type must be std::pair<Key, T>
BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
}
@@ -1326,7 +1326,7 @@ class flat_multimap
const allocator_type& a = allocator_type())
: m_flat_tree(ordered_range, il.begin(), il.end(), comp, a)
{
//A type must be std::pair<Key, T>
//value_type must be std::pair<Key, T>
BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
}
#endif
@@ -1337,7 +1337,7 @@ class flat_multimap
flat_multimap(const flat_multimap& x)
: m_flat_tree(x.m_flat_tree)
{
//A type must be std::pair<Key, T>
//value_type must be std::pair<Key, T>
BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
}
@@ -1350,7 +1350,7 @@ class flat_multimap
BOOST_NOEXCEPT_IF(boost::container::container_detail::is_nothrow_move_constructible<Compare>::value)
: m_flat_tree(boost::move(x.m_flat_tree))
{
//A type must be std::pair<Key, T>
//value_type must be std::pair<Key, T>
BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
}
@@ -1360,7 +1360,7 @@ class flat_multimap
flat_multimap(const flat_multimap& x, const allocator_type &a)
: m_flat_tree(x.m_flat_tree, a)
{
//A type must be std::pair<Key, T>
//value_type must be std::pair<Key, T>
BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
}
@@ -1371,7 +1371,7 @@ class flat_multimap
flat_multimap(BOOST_RV_REF(flat_multimap) x, const allocator_type &a)
: m_flat_tree(boost::move(x.m_flat_tree), a)
{
//A type must be std::pair<Key, T>
//value_type must be std::pair<Key, T>
BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
}

View File

@@ -169,7 +169,7 @@ class flat_set
flat_set(ordered_unique_range_t, InputIterator first, InputIterator last,
const Compare& comp = Compare(),
const allocator_type& a = allocator_type())
: base_t(ordered_range, first, last, comp, a)
: base_t(ordered_unique_range, first, last, comp, a)
{}
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
@@ -204,7 +204,7 @@ class flat_set
//! <b>Note</b>: Non-standard extension.
flat_set(ordered_unique_range_t, std::initializer_list<value_type> il,
const Compare& comp = Compare(), const allocator_type& a = allocator_type())
: base_t(ordered_range, il.begin(), il.end(), comp, a)
: base_t(ordered_unique_range, il.begin(), il.end(), comp, a)
{}
#endif
@@ -959,8 +959,16 @@ class flat_multiset
: base_t(false, il.begin(), il.end(), Compare(), a)
{}
//! @copydoc ::boost::container::flat_set::flat_set(ordered_unique_range_t, std::initializer_list<value_type>, const Compare& comp, const allocator_type&)
flat_multiset(ordered_unique_range_t, std::initializer_list<value_type> il,
//! <b>Effects</b>: Constructs an empty container using the specified comparison object and
//! allocator, and inserts elements from the ordered unique range [il.begin(), il.end()). This function
//! is more efficient than the normal range creation for ordered ranges.
//!
//! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate.
//!
//! <b>Complexity</b>: Linear in N.
//!
//! <b>Note</b>: Non-standard extension.
flat_multiset(ordered_range_t, std::initializer_list<value_type> il,
const Compare& comp = Compare(), const allocator_type& a = allocator_type())
: base_t(ordered_range, il.begin(), il.end(), comp, a)
{}

View File

@@ -245,6 +245,9 @@
<File
RelativePath="..\..\..\..\boost\container\detail\hash_table.hpp">
</File>
<File
RelativePath="..\..\..\..\boost\container\detail\is_sorted.hpp">
</File>
<File
RelativePath="..\..\..\..\boost\container\detail\iterator.hpp">
</File>