Improvements to aged_containers (RIPD-363)

- Added unit tests for element erase
- Added unit tests for range erase
- Added unit tests for touch
- Added unit tests for iterators and reverse_iterators
- Un-inlined operator== for unordered containers
- Fixed minor problems with ordered_container erase()
- Made ordered_container...
  - erase (reverse_iterator pos) not compile
  - erase (reverse_iterator first, reverse_iterator last) not compile
  - touch (reverse iterator pos) not compile
- Verified that ordered container...
  - insert() already rejects reverse_iterator
  - emplace_hint() already rejects reverse_iterator
- Made set/multiset iterators const

Regarding the set/multiset iterators, see section 1.5 of
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2913.pdf
as pointed out by Vinnie.
This commit is contained in:
Scott Schurr
2014-07-23 15:55:13 -07:00
committed by Vinnie Falco
parent ee570a49d0
commit df32f27762
4 changed files with 706 additions and 138 deletions

View File

@@ -42,6 +42,18 @@
namespace beast {
namespace detail {
// Traits templates used to discern reverse_iterators, which are disallowed
// for mutating operations.
template <class It>
struct is_boost_reverse_iterator
: std::false_type
{};
template <class It>
struct is_boost_reverse_iterator<boost::intrusive::detail::reverse_iterator<It>>
: std::true_type
{};
/** Associative container where each element is also indexed by time.
This container mirrors the interface of the standard library ordered
@@ -203,7 +215,7 @@ private:
{
return this->member() (k, extract (e.value));
}
template <class K>
bool operator() (element const& e, K const& k) const
{
@@ -215,7 +227,7 @@ private:
{
return this->member() (k, extract (e.value));
}
bool operator() (element const& e, Key const& k) const
{
return this->member() (extract (e.value), k);
@@ -384,13 +396,14 @@ private:
return p;
}
void delete_element (element* p)
void delete_element (element const* p)
{
ElementAllocatorTraits::destroy (m_config.alloc(), p);
ElementAllocatorTraits::deallocate (m_config.alloc(), p, 1);
ElementAllocatorTraits::deallocate (
m_config.alloc(), const_cast<element*>(p), 1);
}
void unlink_and_delete_element (element* p)
void unlink_and_delete_element (element const* p)
{
chronological.list.erase (
chronological.list.iterator_to (*p));
@@ -412,11 +425,13 @@ public:
typedef typename std::allocator_traits <
Allocator>::const_pointer const_pointer;
typedef detail::aged_container_iterator <false,
// A set (that is, !IsMap) iterator is aways const because the elements
// of a set are immutable.
typedef detail::aged_container_iterator <!IsMap,
typename cont_type::iterator> iterator;
typedef detail::aged_container_iterator <true,
typename cont_type::iterator> const_iterator;
typedef detail::aged_container_iterator <false,
typedef detail::aged_container_iterator <!IsMap,
typename cont_type::reverse_iterator> reverse_iterator;
typedef detail::aged_container_iterator <true,
typename cont_type::reverse_iterator> const_reverse_iterator;
@@ -433,11 +448,13 @@ public:
class chronological_t
{
public:
typedef detail::aged_container_iterator <false,
// A set (that is, !IsMap) iterator is aways const because the elements
// of a set are immutable.
typedef detail::aged_container_iterator <!IsMap,
typename list_type::iterator> iterator;
typedef detail::aged_container_iterator <true,
typename list_type::iterator> const_iterator;
typedef detail::aged_container_iterator <false,
typedef detail::aged_container_iterator <!IsMap,
typename list_type::reverse_iterator> reverse_iterator;
typedef detail::aged_container_iterator <true,
typename list_type::reverse_iterator> const_reverse_iterator;
@@ -823,7 +840,7 @@ public:
template <bool maybe_multi = IsMulti>
typename std::enable_if <maybe_multi,
iterator>::type
insert (const_iterator const& /*hint*/, value_type const& value)
insert (const_iterator /*hint*/, value_type const& value)
{
// VFALCO TODO Figure out how to utilize 'hint'
return insert (value);
@@ -840,7 +857,7 @@ public:
template <bool maybe_multi = IsMulti>
typename std::enable_if <maybe_multi,
iterator>::type
insert (const_iterator const& /*hint*/, value_type&& value)
insert (const_iterator /*hint*/, value_type&& value)
{
// VFALCO TODO Figure out how to utilize 'hint'
return insert (std::move (value));
@@ -882,7 +899,7 @@ public:
template <class InputIt>
void
insert (InputIt first, InputIt const& last)
insert (InputIt first, InputIt last)
{
for (; first != last; ++first)
insert (cend(), *first);
@@ -911,7 +928,7 @@ public:
// map, set
template <bool maybe_multi = IsMulti, class... Args>
auto
emplace_hint (const_iterator const& hint, Args&&... args) ->
emplace_hint (const_iterator hint, Args&&... args) ->
typename std::enable_if <! maybe_multi,
std::pair <iterator, bool>>::type;
@@ -919,24 +936,26 @@ public:
template <bool maybe_multi = IsMulti, class... Args>
typename std::enable_if <maybe_multi,
iterator>::type
emplace_hint (const_iterator const& /*hint*/, Args&&... args)
emplace_hint (const_iterator /*hint*/, Args&&... args)
{
// VFALCO TODO Figure out how to utilize 'hint'
return emplace <maybe_multi> (
std::forward <Args> (args)...);
}
template <bool is_const, class Iterator, class Base>
// enable_if prevents erase (reverse_iterator pos) from compiling
template <bool is_const, class Iterator, class Base,
class = std::enable_if_t<!is_boost_reverse_iterator<Iterator>::value>>
detail::aged_container_iterator <false, Iterator, Base>
erase (detail::aged_container_iterator <
is_const, Iterator, Base> const& pos);
erase (detail::aged_container_iterator <is_const, Iterator, Base> pos);
template <bool is_const, class Iterator, class Base>
// enable_if prevents erase (reverse_iterator first, reverse_iterator last)
// from compiling
template <bool is_const, class Iterator, class Base,
class = std::enable_if_t<!is_boost_reverse_iterator<Iterator>::value>>
detail::aged_container_iterator <false, Iterator, Base>
erase (detail::aged_container_iterator <
is_const, Iterator, Base> first,
detail::aged_container_iterator <
is_const, Iterator, Base> const& last);
erase (detail::aged_container_iterator <is_const, Iterator, Base> first,
detail::aged_container_iterator <is_const, Iterator, Base> last);
template <class K>
auto
@@ -948,10 +967,11 @@ public:
//--------------------------------------------------------------------------
template <bool is_const, class Iterator, class Base>
// enable_if prevents touch (reverse_iterator pos) from compiling
template <bool is_const, class Iterator, class Base,
class = std::enable_if_t<!is_boost_reverse_iterator<Iterator>::value>>
void
touch (detail::aged_container_iterator <
is_const, Iterator, Base> const& pos)
touch (detail::aged_container_iterator <is_const, Iterator, Base> pos)
{
touch (pos, clock().now());
}
@@ -1047,7 +1067,7 @@ public:
const_iterator
upper_bound (K const& k) const
{
return const_iterator (m_cont.upper_bound (k,
return const_iterator (m_cont.upper_bound (k,
std::cref (m_config.key_compare())));
}
@@ -1176,10 +1196,12 @@ public:
}
private:
template <bool is_const, class Iterator, class Base>
// enable_if prevents erase (reverse_iterator pos, now) from compiling
template <bool is_const, class Iterator, class Base,
class = std::enable_if_t<!is_boost_reverse_iterator<Iterator>::value>>
void
touch (detail::aged_container_iterator <
is_const, Iterator, Base> const& pos,
is_const, Iterator, Base> pos,
typename clock_type::time_point const& now);
template <bool maybe_propagate = std::allocator_traits <
@@ -1693,7 +1715,7 @@ template <bool IsMulti, bool IsMap, class Key, class T,
template <bool maybe_multi, class... Args>
auto
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
emplace_hint (const_iterator const& hint, Args&&... args) ->
emplace_hint (const_iterator hint, Args&&... args) ->
typename std::enable_if <! maybe_multi,
std::pair <iterator, bool>>::type
{
@@ -1716,36 +1738,27 @@ emplace_hint (const_iterator const& hint, Args&&... args) ->
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Compare, class Allocator>
template <bool is_const, class Iterator, class Base>
auto
template <bool is_const, class Iterator, class Base, class>
detail::aged_container_iterator <false, Iterator, Base>
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
erase (detail::aged_container_iterator <
is_const, Iterator, Base> const& pos) ->
detail::aged_container_iterator <false, Iterator, Base>
erase (detail::aged_container_iterator <is_const, Iterator, Base> pos)
{
auto iter (pos.iterator());
auto p (&*iter++);
unlink_and_delete_element (p);
unlink_and_delete_element(&*((pos++).iterator()));
return detail::aged_container_iterator <
false, Iterator, Base> (iter);
false, Iterator, Base> (pos.iterator());
}
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Compare, class Allocator>
template <bool is_const, class Iterator, class Base>
auto
template <bool is_const, class Iterator, class Base, class>
detail::aged_container_iterator <false, Iterator, Base>
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
erase (detail::aged_container_iterator <
is_const, Iterator, Base> first,
detail::aged_container_iterator <
is_const, Iterator, Base> const& last) ->
detail::aged_container_iterator <false, Iterator, Base>
erase (detail::aged_container_iterator <is_const, Iterator, Base> first,
detail::aged_container_iterator <is_const, Iterator, Base> last)
{
for (; first != last;)
{
auto p (&*first++);
unlink_and_delete_element (p);
}
unlink_and_delete_element(&*((first++).iterator()));
return detail::aged_container_iterator <
false, Iterator, Base> (first.iterator());
}
@@ -1839,11 +1852,11 @@ operator== (
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Compare, class Allocator>
template <bool is_const, class Iterator, class Base>
template <bool is_const, class Iterator, class Base, class>
void
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
touch (detail::aged_container_iterator <
is_const, Iterator, Base> const& pos,
is_const, Iterator, Base> pos,
typename clock_type::time_point const& now)
{
auto& e (*pos.iterator());