Commit e9afbed0 by François Dumont

re PR libstdc++/68222 (_Safe_iterator provides operators the wrapped iterator…

re PR libstdc++/68222 (_Safe_iterator provides operators the wrapped iterator can't actually support)

2018-08-22  François Dumont  <fdumont@gcc.gnu.org>

	PR libstdc++/68222
	* include/debug/safe_iterator.h
	(_Safe_iterator<_It, _Sq, _Cat>): Add category template parameter.
	(_Safe_iterator<>::_Const_iterator): Remove.
	(_Safe_iterator<>::_IsConstant): New.
	(_Safe_iterator<>::_OtherIterator): New.
	(_Safe_iterator<_It, _Sq, _Cat>::_Safe_iterator<_MutIte>(
	const _Safe_iterator<_MutIte, _Sq, _Cat>&)): Add _IsConstant::__value in
	__gnu_cxx::__enable_if condition.
	(_Safe_iterator<_It, _Sq, _Cat>::_M_get_distance_to): New.
	(_Safe_iterator<_It, _Sq, _Cat>::_M_get_distance_from_begin): New.
	(_Safe_iterator<_It, _Sq, _Cat>::_M_get_distance_to_end): New.
	(_Safe_iterator<_It, _Sq, std::bidirectional_iterator_tag>): New.
	(_Safe_iterator<_It, _Sq, _Cat>::operator--()): Move...
	(_Safe_iterator<_It, _Sq, std::bidirectional_iterator_tag>
	::operator--()): ...here.
	(_Safe_iterator<_It, _Sq, _Cat>::operator--(int)): Move...
	(_Safe_iterator<_It, _Sq, std::bidirectional_iterator_tag>
	::operator--(int)): ...here.
	(_Safe_iterator<_It, _Sq, _Cat>::_M_decrementable()): Move...
	(_Safe_iterator<_It, _Sq, std::bidirectional_iterator_tag>
	::_M_decrementable()): ...here.
	(_Safe_iterator<_It, _Sq, std::random_access_iterator_tag>): New.
	(_Safe_iterator<_It, _Sq, _Cat>::operator[](const difference_type&)):
	Move...
	(_Safe_iterator<_It, _Sq, std::random_access_iterator_tag>
	::operator[](const difference_type&)): ...here.
	(_Safe_iterator<_It, _Sq, _Cat>::operator+=(const difference_type&)):
	Move...
	(_Safe_iterator<_It, _Sq, std::random_access_iterator_tag>
	::operator+=(const difference_type&)): ...here.
	(_Safe_iterator<_It, _Sq, _Cat>::operator+(const difference_type&)):
	Move...
	(_Safe_iterator<_It, _Sq, std::random_access_iterator_tag>
	::operator+(const difference_type&)): ...here.
	(_Safe_iterator<_It, _Sq, _Cat>::operator-=(const difference_type&)):
	Move...
	(_Safe_iterator<_It, _Sq, std::random_access_iterator_tag>
	::operator-=(const difference_type&)): ...here.
	(_Safe_iterator<_It, _Sq, _Cat>::operator-(const difference_type&)):
	Move...
	(_Safe_iterator<_It, _Sq, std::random_access_iterator_tag>
	::operator-(const difference_type&)): ...here.
	(operator<(const _Safe_iterator<>&, const _Safe_iterator<>&)):
	Constraint to random access iterators.
	(operator<=(const _Safe_iterator<>&, const _Safe_iterator<>&)):
	Likewise.
	(operator>(const _Safe_iterator<>&, const _Safe_iterator<>&)): Likewise.
	(operator>=(const _Safe_iterator<>&, const _Safe_iterator<>&)):
	Likewise.
	(operator-(const _Safe_iterator<>&, const _Safe_iterator<>&)): Likewise.
	(operator+(const difference_type&, const _Safe_iterator<>&)): Likewise.
	(__check_dereferenceable(const _Safe_iterator<>&)): Remove.
	(__get_distance): Remove.
	(__get_distance_from_begin): Remove.
	(__get_distance_to_end): Remove.
	(struct __is_safe_random_iterator<_Safe_iterator<>>): Remove partial
	specialization.
	(__base(const _Safe_iterator<>&, std::input_iterator_tag)): Remove.
	(__base(const _Safe_iterator<>&, std::random_access_iterator_tag)): Remove.
	(__base(const _Safe_iterator<>&)): Constraint to random access iterator.
	* include/debug/safe_iterator.tcc
	(_Safe_iterator<>::_M_get_distance_from_begin()): New.
	(_Safe_iterator<>::_M_get_distance_to_end()): New.
	(_Safe_iterator<>::_M_get_distance_to(const _Safe_iterator<>&)): New.
	(_Safe_iterator<_It, _Seq, std::random_access_iterator_tag>
	::_M_valid_range): New.
	* include/debug/safe_local_iterator.h
	(_Safe_local_iterator<>::_Const_local_iterator): Remove.
	(_Safe_local_iterator<>::_IsConstant): New.
	(_Safe_local_iterator<>::_OtherIterator): New.
	(_Safe_local_iterator<_It, _Cont>::_Safe_local_iterator<_MutIte, _Cont>(
	const _Safe_local_iterator<_MutIte, _Seq>&)): Add _IsConstant::__value
	in __gnu_cxx::__enable_if condition. If singular compare base iterator
	with _MutIte rather than _It.
	(_Safe_local_iterator<>::_S_constant): Make constexpr.
	(_Safe_local_iterator<>::_M_get_distance_to): New.
	(__check_dereferenceable(const _Safe_local_iterator<>&)): Remove.
	(__get_distance(const _Safe_local_iterator<>&,
	const _Safe_local_iterator<>&, std::input_iterator_tag)): Remove.
	(__valid_range(const _Safe_local_iterator<>&,
	const _Safe_local_iterator<>&)): New.
	* include/debug/safe_local_iterator.tcc
	(_Safe_local_iterator<>::_M_get_distance_to): New.
	* include/debug/deque (std::__debug::deque<>): Add
	::__gnu_debug::_Safe_iterator<> friend declaration.
	* include/debug/forward_list (std::__debug::forward_list<>): Likewise.
	* include/debug/list (std::__debug::list<>): Likewise.
	* include/debug/map.h (std::__debug::map<>): Likewise.
	* include/debug/multimap.h (std::__debug::multimap<>): Likewise.
	* include/debug/set.h (std::__debug::set<>): Likewise.
	* include/debug/multiset.h (std::__debug::multiset<>): Likewise.
	* include/debug/string (std::__debug::basic_string<>): Likewise.
	* include/debug/unordered_map (std::__debug::unordered_map<>): Likewise
	and add ::__gnu_debug::_Safe_local_iterator<> friend declaration.
	(std::__debug::unordered_multimap<>): Likewise.
	* include/debug/unordered_set (std::__debug::unordered_set<>): Likewise.
	(std::__debug::unordered_multiset<>): Likewise.
	* include/debug/formatter.h: Adapt.
	* include/debug/helper_functions.h
	(__gnu_debug::_Safe_local_iterator<>): Add declaration.
	(__get_distance<_Ite>(_Ite, _Ite, std::random_access_iterator_tag):
	Pass parameter by copy.
	(__get_distance<_Ite>(_Ite, _Ite, std::input_iterator_tag): Likewise.
	(__get_distance<_Ite>(_Ite, _Ite): Likewise.
	(__valid_range_aux<_Integral>): Pass _Integral by copy.
	(__valid_range<_InputIterator>): Pass _InputIterator by copy.
	(__valid_range<>(const _Safe_iterator<>&,
	const _Safe_iterator<>&, typename _Distance_traits<>::__type&)):
	Declare.
	(__valid_range(const _Safe_local_iterator<>&,
	const _Safe_local_iterator<>&, typename _Distance_traits<>::__type&)):
	Declare.
	(__valid_range<>(const _Safe_iterator<>&, const _Safe_iterator<>&)):
	Declare.
	(__valid_range(const _Safe_local_iterator<>&, const _Safe_local_iterator<>&)):
	Declare.
	(__can_advance): Adapt.
	(struct __is_safe_random_iterator<>): Remove.
	(struct _SIter_base<>): Remove.
	* include/debug/functions.h: Include <bits/stl_iterator.h>.
	(__check_dereferenceable): Remove.
	(__foreign_iterator_aux4, __foreign_iterator_aux3): Adapt.
	(__foreign_iterator_aux2, __foreign_iterator_aux): Adapt.
	(__foreign_iterator): Adapt.
	* include/debug/stl_iterator.h
	(__is_safe_random_iterator<std::reverse_iterator<>>): Remove.
	(__base(const std::reverse_iterator<_Safe_iterator<_It, _Sq>)):
	Constraint for random access iterators.
	(__niter_base): Adapt.
	* testsuite/util/testsuite_containers.h:
	Include <bits/boost_concept_check.h>.
	(iterator_concept_checks<_It, _Mutable, _Category>): New.
	(citerator<_Cont>::forward_members::forward_members()): Instantiate
	latter for container iterator and const_iterator.
	* testsuite/23_containers/list/68222_neg.cc: New.
	* testsuite/23_containers/vector/cons/destructible_debug_neg.cc: Adapt
	line number.
	* testsuite/23_containers/unordered_set/debug/debug_functions.cc:
	(test01): Remove.
	* testsuite/23_containers/vector/debug/debug_functions.cc (test01):
	Remove.

From-SVN: r263786
parent 66f32b0e
2018-08-22 François Dumont <fdumont@gcc.gnu.org>
PR libstdc++/68222
* include/debug/safe_iterator.h
(_Safe_iterator<_It, _Sq, _Cat>): Add category template parameter.
(_Safe_iterator<>::_Const_iterator): Remove.
(_Safe_iterator<>::_IsConstant): New.
(_Safe_iterator<>::_OtherIterator): New.
(_Safe_iterator<_It, _Sq, _Cat>::_Safe_iterator<_MutIte>(
const _Safe_iterator<_MutIte, _Sq, _Cat>&)): Add _IsConstant::__value in
__gnu_cxx::__enable_if condition.
(_Safe_iterator<_It, _Sq, _Cat>::_M_get_distance_to): New.
(_Safe_iterator<_It, _Sq, _Cat>::_M_get_distance_from_begin): New.
(_Safe_iterator<_It, _Sq, _Cat>::_M_get_distance_to_end): New.
(_Safe_iterator<_It, _Sq, std::bidirectional_iterator_tag>): New.
(_Safe_iterator<_It, _Sq, _Cat>::operator--()): Move...
(_Safe_iterator<_It, _Sq, std::bidirectional_iterator_tag>
::operator--()): ...here.
(_Safe_iterator<_It, _Sq, _Cat>::operator--(int)): Move...
(_Safe_iterator<_It, _Sq, std::bidirectional_iterator_tag>
::operator--(int)): ...here.
(_Safe_iterator<_It, _Sq, _Cat>::_M_decrementable()): Move...
(_Safe_iterator<_It, _Sq, std::bidirectional_iterator_tag>
::_M_decrementable()): ...here.
(_Safe_iterator<_It, _Sq, std::random_access_iterator_tag>): New.
(_Safe_iterator<_It, _Sq, _Cat>::operator[](const difference_type&)):
Move...
(_Safe_iterator<_It, _Sq, std::random_access_iterator_tag>
::operator[](const difference_type&)): ...here.
(_Safe_iterator<_It, _Sq, _Cat>::operator+=(const difference_type&)):
Move...
(_Safe_iterator<_It, _Sq, std::random_access_iterator_tag>
::operator+=(const difference_type&)): ...here.
(_Safe_iterator<_It, _Sq, _Cat>::operator+(const difference_type&)):
Move...
(_Safe_iterator<_It, _Sq, std::random_access_iterator_tag>
::operator+(const difference_type&)): ...here.
(_Safe_iterator<_It, _Sq, _Cat>::operator-=(const difference_type&)):
Move...
(_Safe_iterator<_It, _Sq, std::random_access_iterator_tag>
::operator-=(const difference_type&)): ...here.
(_Safe_iterator<_It, _Sq, _Cat>::operator-(const difference_type&)):
Move...
(_Safe_iterator<_It, _Sq, std::random_access_iterator_tag>
::operator-(const difference_type&)): ...here.
(operator<(const _Safe_iterator<>&, const _Safe_iterator<>&)):
Constraint to random access iterators.
(operator<=(const _Safe_iterator<>&, const _Safe_iterator<>&)):
Likewise.
(operator>(const _Safe_iterator<>&, const _Safe_iterator<>&)): Likewise.
(operator>=(const _Safe_iterator<>&, const _Safe_iterator<>&)):
Likewise.
(operator-(const _Safe_iterator<>&, const _Safe_iterator<>&)): Likewise.
(operator+(const difference_type&, const _Safe_iterator<>&)): Likewise.
(__check_dereferenceable(const _Safe_iterator<>&)): Remove.
(__get_distance): Remove.
(__get_distance_from_begin): Remove.
(__get_distance_to_end): Remove.
(struct __is_safe_random_iterator<_Safe_iterator<>>): Remove partial
specialization.
(__base(const _Safe_iterator<>&, std::input_iterator_tag)): Remove.
(__base(const _Safe_iterator<>&, std::random_access_iterator_tag)): Remove.
(__base(const _Safe_iterator<>&)): Constraint to random access iterator.
* include/debug/safe_iterator.tcc
(_Safe_iterator<>::_M_get_distance_from_begin()): New.
(_Safe_iterator<>::_M_get_distance_to_end()): New.
(_Safe_iterator<>::_M_get_distance_to(const _Safe_iterator<>&)): New.
(_Safe_iterator<_It, _Seq, std::random_access_iterator_tag>
::_M_valid_range): New.
* include/debug/safe_local_iterator.h
(_Safe_local_iterator<>::_Const_local_iterator): Remove.
(_Safe_local_iterator<>::_IsConstant): New.
(_Safe_local_iterator<>::_OtherIterator): New.
(_Safe_local_iterator<_It, _Cont>::_Safe_local_iterator<_MutIte, _Cont>(
const _Safe_local_iterator<_MutIte, _Seq>&)): Add _IsConstant::__value
in __gnu_cxx::__enable_if condition. If singular compare base iterator
with _MutIte rather than _It.
(_Safe_local_iterator<>::_S_constant): Make constexpr.
(_Safe_local_iterator<>::_M_get_distance_to): New.
(__check_dereferenceable(const _Safe_local_iterator<>&)): Remove.
(__get_distance(const _Safe_local_iterator<>&,
const _Safe_local_iterator<>&, std::input_iterator_tag)): Remove.
(__valid_range(const _Safe_local_iterator<>&,
const _Safe_local_iterator<>&)): New.
* include/debug/safe_local_iterator.tcc
(_Safe_local_iterator<>::_M_get_distance_to): New.
* include/debug/deque (std::__debug::deque<>): Add
::__gnu_debug::_Safe_iterator<> friend declaration.
* include/debug/forward_list (std::__debug::forward_list<>): Likewise.
* include/debug/list (std::__debug::list<>): Likewise.
* include/debug/map.h (std::__debug::map<>): Likewise.
* include/debug/multimap.h (std::__debug::multimap<>): Likewise.
* include/debug/set.h (std::__debug::set<>): Likewise.
* include/debug/multiset.h (std::__debug::multiset<>): Likewise.
* include/debug/string (std::__debug::basic_string<>): Likewise.
* include/debug/unordered_map (std::__debug::unordered_map<>): Likewise
and add ::__gnu_debug::_Safe_local_iterator<> friend declaration.
(std::__debug::unordered_multimap<>): Likewise.
* include/debug/unordered_set (std::__debug::unordered_set<>): Likewise.
(std::__debug::unordered_multiset<>): Likewise.
* include/debug/formatter.h: Adapt.
* include/debug/helper_functions.h
(__gnu_debug::_Safe_local_iterator<>): Add declaration.
(__get_distance<_Ite>(_Ite, _Ite, std::random_access_iterator_tag):
Pass parameter by copy.
(__get_distance<_Ite>(_Ite, _Ite, std::input_iterator_tag): Likewise.
(__get_distance<_Ite>(_Ite, _Ite): Likewise.
(__valid_range_aux<_Integral>): Pass _Integral by copy.
(__valid_range<_InputIterator>): Pass _InputIterator by copy.
(__valid_range<>(const _Safe_iterator<>&,
const _Safe_iterator<>&, typename _Distance_traits<>::__type&)):
Declare.
(__valid_range(const _Safe_local_iterator<>&,
const _Safe_local_iterator<>&, typename _Distance_traits<>::__type&)):
Declare.
(__valid_range<>(const _Safe_iterator<>&, const _Safe_iterator<>&)):
Declare.
(__valid_range(const _Safe_local_iterator<>&, const _Safe_local_iterator<>&)):
Declare.
(__can_advance): Adapt.
(struct __is_safe_random_iterator<>): Remove.
(struct _SIter_base<>): Remove.
* include/debug/functions.h: Include <bits/stl_iterator.h>.
(__check_dereferenceable): Remove.
(__foreign_iterator_aux4, __foreign_iterator_aux3): Adapt.
(__foreign_iterator_aux2, __foreign_iterator_aux): Adapt.
(__foreign_iterator): Adapt.
* include/debug/stl_iterator.h
(__is_safe_random_iterator<std::reverse_iterator<>>): Remove.
(__base(const std::reverse_iterator<_Safe_iterator<_It, _Sq>)):
Constraint for random access iterators.
(__niter_base): Adapt.
* testsuite/util/testsuite_containers.h:
Include <bits/boost_concept_check.h>.
(iterator_concept_checks<_It, _Mutable, _Category>): New.
(citerator<_Cont>::forward_members::forward_members()): Instantiate
latter for container iterator and const_iterator.
* testsuite/23_containers/list/68222_neg.cc: New.
* testsuite/23_containers/vector/cons/destructible_debug_neg.cc: Adapt
line number.
* testsuite/23_containers/unordered_set/debug/debug_functions.cc:
(test01): Remove.
* testsuite/23_containers/vector/debug/debug_functions.cc (test01):
Remove.
2018-08-22 Jonathan Wakely <jwakely@redhat.com> 2018-08-22 Jonathan Wakely <jwakely@redhat.com>
PR libstdc++/77854 PR libstdc++/77854
......
...@@ -56,6 +56,9 @@ namespace __debug ...@@ -56,6 +56,9 @@ namespace __debug
typedef typename _Base::iterator _Base_iterator; typedef typename _Base::iterator _Base_iterator;
typedef __gnu_debug::_Equal_to<_Base_const_iterator> _Equal; typedef __gnu_debug::_Equal_to<_Base_const_iterator> _Equal;
template<typename _ItT, typename _SeqT, typename _CatT>
friend class ::__gnu_debug::_Safe_iterator;
public: public:
typedef typename _Base::reference reference; typedef typename _Base::reference reference;
typedef typename _Base::const_reference const_reference; typedef typename _Base::const_reference const_reference;
......
...@@ -76,7 +76,7 @@ namespace __gnu_debug ...@@ -76,7 +76,7 @@ namespace __gnu_debug
class _Safe_sequence_base; class _Safe_sequence_base;
template<typename _Iterator, typename _Sequence> template<typename _Iterator, typename _Sequence, typename _Category>
class _Safe_iterator; class _Safe_iterator;
template<typename _Iterator, typename _Sequence> template<typename _Iterator, typename _Sequence>
...@@ -263,8 +263,8 @@ namespace __gnu_debug ...@@ -263,8 +263,8 @@ namespace __gnu_debug
_M_variant._M_string._M_value = __value; _M_variant._M_string._M_value = __value;
} }
template<typename _Iterator, typename _Sequence> template<typename _Iterator, typename _Sequence, typename _Category>
_Parameter(_Safe_iterator<_Iterator, _Sequence> const& __it, _Parameter(_Safe_iterator<_Iterator, _Sequence, _Category> const& __it,
const char* __name, _Is_iterator) const char* __name, _Is_iterator)
: _M_kind(__iterator), _M_variant() : _M_kind(__iterator), _M_variant()
{ {
...@@ -378,10 +378,10 @@ namespace __gnu_debug ...@@ -378,10 +378,10 @@ namespace __gnu_debug
= _S_reverse_state(_M_variant._M_iterator._M_state); = _S_reverse_state(_M_variant._M_iterator._M_state);
} }
template<typename _Iterator, typename _Sequence> template<typename _Iterator, typename _Sequence, typename _Category>
_Parameter(std::reverse_iterator<_Safe_iterator<_Iterator, _Parameter(std::reverse_iterator<_Safe_iterator<_Iterator, _Sequence,
_Sequence>> const& __it, _Category>> const& __it,
const char* __name, _Is_iterator) const char* __name, _Is_iterator)
: _Parameter(__it.base(), __name, _Is_iterator{}) : _Parameter(__it.base(), __name, _Is_iterator{})
{ {
_M_variant._M_iterator._M_type _M_variant._M_iterator._M_type
...@@ -396,10 +396,10 @@ namespace __gnu_debug ...@@ -396,10 +396,10 @@ namespace __gnu_debug
: _Parameter(__it.base(), __name, _Is_iterator{}) : _Parameter(__it.base(), __name, _Is_iterator{})
{ _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(__it); } { _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(__it); }
template<typename _Iterator, typename _Sequence> template<typename _Iterator, typename _Sequence, typename _Category>
_Parameter(std::move_iterator<_Safe_iterator<_Iterator, _Parameter(std::move_iterator<_Safe_iterator<_Iterator, _Sequence,
_Sequence>> const& __it, _Category>> const& __it,
const char* __name, _Is_iterator) const char* __name, _Is_iterator)
: _Parameter(__it.base(), __name, _Is_iterator{}) : _Parameter(__it.base(), __name, _Is_iterator{})
{ {
_M_variant._M_iterator._M_type _M_variant._M_iterator._M_type
......
...@@ -193,6 +193,9 @@ namespace __debug ...@@ -193,6 +193,9 @@ namespace __debug
typedef typename _Base::iterator _Base_iterator; typedef typename _Base::iterator _Base_iterator;
typedef typename _Base::const_iterator _Base_const_iterator; typedef typename _Base::const_iterator _Base_const_iterator;
template<typename _ItT, typename _SeqT, typename _CatT>
friend class ::__gnu_debug::_Safe_iterator;
public: public:
typedef typename _Base::reference reference; typedef typename _Base::reference reference;
typedef typename _Base::const_reference const_reference; typedef typename _Base::const_reference const_reference;
......
...@@ -31,7 +31,9 @@ ...@@ -31,7 +31,9 @@
#include <bits/move.h> // for __addressof #include <bits/move.h> // for __addressof
#include <bits/stl_function.h> // for less #include <bits/stl_function.h> // for less
#if __cplusplus >= 201103L #if __cplusplus >= 201103L
# include <bits/stl_iterator.h> // for __miter_base
# include <type_traits> // for is_lvalue_reference and conditional. # include <type_traits> // for is_lvalue_reference and conditional.
#endif #endif
...@@ -64,19 +66,6 @@ namespace __gnu_debug ...@@ -64,19 +66,6 @@ namespace __gnu_debug
__check_singular(const _Tp* __ptr) __check_singular(const _Tp* __ptr)
{ return __ptr == 0; } { return __ptr == 0; }
/** Assume that some arbitrary iterator is dereferenceable, because we
can't prove that it isn't. */
template<typename _Iterator>
inline bool
__check_dereferenceable(const _Iterator&)
{ return true; }
/** Non-NULL pointers are dereferenceable. */
template<typename _Tp>
inline bool
__check_dereferenceable(const _Tp* __ptr)
{ return __ptr; }
/* Checks that [first, last) is a valid range, and then returns /* Checks that [first, last) is a valid range, and then returns
* __first. This routine is useful when we can't use a separate * __first. This routine is useful when we can't use a separate
* assertion statement because, e.g., we are in a constructor. * assertion statement because, e.g., we are in a constructor.
...@@ -95,10 +84,11 @@ namespace __gnu_debug ...@@ -95,10 +84,11 @@ namespace __gnu_debug
} }
/* Handle the case where __other is a pointer to _Sequence::value_type. */ /* Handle the case where __other is a pointer to _Sequence::value_type. */
template<typename _Iterator, typename _Sequence> template<typename _Iterator, typename _Sequence, typename _Category>
inline bool inline bool
__foreign_iterator_aux4(const _Safe_iterator<_Iterator, _Sequence>& __it, __foreign_iterator_aux4(
const typename _Sequence::value_type* __other) const _Safe_iterator<_Iterator, _Sequence, _Category>& __it,
const typename _Sequence::value_type* __other)
{ {
typedef const typename _Sequence::value_type* _PointerType; typedef const typename _Sequence::value_type* _PointerType;
typedef std::less<_PointerType> _Less; typedef std::less<_PointerType> _Less;
...@@ -116,18 +106,20 @@ namespace __gnu_debug ...@@ -116,18 +106,20 @@ namespace __gnu_debug
} }
/* Fallback overload for when we can't tell, assume it is valid. */ /* Fallback overload for when we can't tell, assume it is valid. */
template<typename _Iterator, typename _Sequence> template<typename _Iterator, typename _Sequence, typename _Category>
inline bool inline bool
__foreign_iterator_aux4(const _Safe_iterator<_Iterator, _Sequence>&, ...) __foreign_iterator_aux4(
const _Safe_iterator<_Iterator, _Sequence, _Category>&, ...)
{ return true; } { return true; }
/* Handle sequences with contiguous storage */ /* Handle sequences with contiguous storage */
template<typename _Iterator, typename _Sequence, typename _InputIterator> template<typename _Iterator, typename _Sequence, typename _Category,
typename _InputIterator>
inline bool inline bool
__foreign_iterator_aux3(const _Safe_iterator<_Iterator, _Sequence>& __it, __foreign_iterator_aux3(
const _InputIterator& __other, const _Safe_iterator<_Iterator, _Sequence, _Category>& __it,
const _InputIterator& __other_end, const _InputIterator& __other, const _InputIterator& __other_end,
std::__true_type) std::__true_type)
{ {
if (__other == __other_end) if (__other == __other_end)
return true; // inserting nothing is safe even if not foreign iters return true; // inserting nothing is safe even if not foreign iters
...@@ -137,36 +129,46 @@ namespace __gnu_debug ...@@ -137,36 +129,46 @@ namespace __gnu_debug
} }
/* Handle non-contiguous containers, assume it is valid. */ /* Handle non-contiguous containers, assume it is valid. */
template<typename _Iterator, typename _Sequence, typename _InputIterator> template<typename _Iterator, typename _Sequence, typename _Category,
typename _InputIterator>
inline bool inline bool
__foreign_iterator_aux3(const _Safe_iterator<_Iterator, _Sequence>&, __foreign_iterator_aux3(
const _InputIterator&, const _InputIterator&, const _Safe_iterator<_Iterator, _Sequence, _Category>&,
std::__false_type) const _InputIterator&, const _InputIterator&,
std::__false_type)
{ return true; } { return true; }
/** Handle debug iterators from the same type of container. */ /** Handle debug iterators from the same type of container. */
template<typename _Iterator, typename _Sequence, typename _OtherIterator> template<typename _Iterator, typename _Sequence, typename _Category,
typename _OtherIterator>
inline bool inline bool
__foreign_iterator_aux2(const _Safe_iterator<_Iterator, _Sequence>& __it, __foreign_iterator_aux2(
const _Safe_iterator<_OtherIterator, _Sequence>& __other, const _Safe_iterator<_Iterator, _Sequence, _Category>& __it,
const _Safe_iterator<_OtherIterator, _Sequence>&) const _Safe_iterator<_OtherIterator, _Sequence, _Category>& __other,
const _Safe_iterator<_OtherIterator, _Sequence, _Category>&)
{ return __it._M_get_sequence() != __other._M_get_sequence(); } { return __it._M_get_sequence() != __other._M_get_sequence(); }
/** Handle debug iterators from different types of container. */ /** Handle debug iterators from different types of container. */
template<typename _Iterator, typename _Sequence, typename _OtherIterator, template<typename _Iterator, typename _Sequence, typename _Category,
typename _OtherSequence> typename _OtherIterator, typename _OtherSequence,
inline bool typename _OtherCategory>
__foreign_iterator_aux2(const _Safe_iterator<_Iterator, _Sequence>& __it, inline bool
const _Safe_iterator<_OtherIterator, _OtherSequence>&, __foreign_iterator_aux2(
const _Safe_iterator<_OtherIterator, _OtherSequence>&) const _Safe_iterator<_Iterator, _Sequence, _Category>&,
const _Safe_iterator<_OtherIterator, _OtherSequence,
_OtherCategory>&,
const _Safe_iterator<_OtherIterator, _OtherSequence,
_OtherCategory>&)
{ return true; } { return true; }
/* Handle non-debug iterators. */ /* Handle non-debug iterators. */
template<typename _Iterator, typename _Sequence, typename _InputIterator> template<typename _Iterator, typename _Sequence, typename _Category,
typename _InputIterator>
inline bool inline bool
__foreign_iterator_aux2(const _Safe_iterator<_Iterator, _Sequence>& __it, __foreign_iterator_aux2(
const _InputIterator& __other, const _Safe_iterator<_Iterator, _Sequence, _Category>& __it,
const _InputIterator& __other_end) const _InputIterator& __other,
const _InputIterator& __other_end)
{ {
#if __cplusplus < 201103L #if __cplusplus < 201103L
typedef _Is_contiguous_sequence<_Sequence> __tag; typedef _Is_contiguous_sequence<_Sequence> __tag;
...@@ -181,31 +183,34 @@ namespace __gnu_debug ...@@ -181,31 +183,34 @@ namespace __gnu_debug
} }
/* Handle the case where we aren't really inserting a range after all */ /* Handle the case where we aren't really inserting a range after all */
template<typename _Iterator, typename _Sequence, typename _Integral> template<typename _Iterator, typename _Sequence, typename _Category,
typename _Integral>
inline bool inline bool
__foreign_iterator_aux(const _Safe_iterator<_Iterator, _Sequence>&, __foreign_iterator_aux(
_Integral, _Integral, const _Safe_iterator<_Iterator, _Sequence, _Category>&,
std::__true_type) _Integral, _Integral, std::__true_type)
{ return true; } { return true; }
/* Handle all iterators. */ /* Handle all iterators. */
template<typename _Iterator, typename _Sequence, template<typename _Iterator, typename _Sequence, typename _Category,
typename _InputIterator> typename _InputIterator>
inline bool inline bool
__foreign_iterator_aux(const _Safe_iterator<_Iterator, _Sequence>& __it, __foreign_iterator_aux(
_InputIterator __other, _InputIterator __other_end, const _Safe_iterator<_Iterator, _Sequence, _Category>& __it,
std::__false_type) _InputIterator __other, _InputIterator __other_end,
std::__false_type)
{ {
return _Insert_range_from_self_is_safe<_Sequence>::__value return _Insert_range_from_self_is_safe<_Sequence>::__value
|| __foreign_iterator_aux2(__it, std::__miter_base(__other), || __foreign_iterator_aux2(__it, std::__miter_base(__other),
std::__miter_base(__other_end)); std::__miter_base(__other_end));
} }
template<typename _Iterator, typename _Sequence, template<typename _Iterator, typename _Sequence, typename _Category,
typename _InputIterator> typename _InputIterator>
inline bool inline bool
__foreign_iterator(const _Safe_iterator<_Iterator, _Sequence>& __it, __foreign_iterator(
_InputIterator __other, _InputIterator __other_end) const _Safe_iterator<_Iterator, _Sequence, _Category>& __it,
_InputIterator __other, _InputIterator __other_end)
{ {
typedef typename std::__is_integer<_InputIterator>::__type _Integral; typedef typename std::__is_integer<_InputIterator>::__type _Integral;
return __foreign_iterator_aux(__it, __other, __other_end, _Integral()); return __foreign_iterator_aux(__it, __other, __other_end, _Integral());
......
...@@ -37,9 +37,14 @@ ...@@ -37,9 +37,14 @@
namespace __gnu_debug namespace __gnu_debug
{ {
template<typename _Iterator, typename _Sequence> template<typename _Iterator, typename _Sequence, typename _Category>
class _Safe_iterator; class _Safe_iterator;
#if __cplusplus >= 201103L
template<typename _Iterator, typename _Sequence>
class _Safe_local_iterator;
#endif
/** The precision to which we can calculate the distance between /** The precision to which we can calculate the distance between
* two iterators. * two iterators.
*/ */
...@@ -83,13 +88,13 @@ namespace __gnu_debug ...@@ -83,13 +88,13 @@ namespace __gnu_debug
*/ */
template<typename _Iterator> template<typename _Iterator>
inline typename _Distance_traits<_Iterator>::__type inline typename _Distance_traits<_Iterator>::__type
__get_distance(const _Iterator& __lhs, const _Iterator& __rhs, __get_distance(_Iterator __lhs, _Iterator __rhs,
std::random_access_iterator_tag) std::random_access_iterator_tag)
{ return std::make_pair(__rhs - __lhs, __dp_exact); } { return std::make_pair(__rhs - __lhs, __dp_exact); }
template<typename _Iterator> template<typename _Iterator>
inline typename _Distance_traits<_Iterator>::__type inline typename _Distance_traits<_Iterator>::__type
__get_distance(const _Iterator& __lhs, const _Iterator& __rhs, __get_distance(_Iterator __lhs, _Iterator __rhs,
std::input_iterator_tag) std::input_iterator_tag)
{ {
if (__lhs == __rhs) if (__lhs == __rhs)
...@@ -100,7 +105,7 @@ namespace __gnu_debug ...@@ -100,7 +105,7 @@ namespace __gnu_debug
template<typename _Iterator> template<typename _Iterator>
inline typename _Distance_traits<_Iterator>::__type inline typename _Distance_traits<_Iterator>::__type
__get_distance(const _Iterator& __lhs, const _Iterator& __rhs) __get_distance(_Iterator __lhs, _Iterator __rhs)
{ return __get_distance(__lhs, __rhs, std::__iterator_category(__lhs)); } { return __get_distance(__lhs, __rhs, std::__iterator_category(__lhs)); }
/** We say that integral types for a valid range, and defer to other /** We say that integral types for a valid range, and defer to other
...@@ -109,7 +114,7 @@ namespace __gnu_debug ...@@ -109,7 +114,7 @@ namespace __gnu_debug
*/ */
template<typename _Integral> template<typename _Integral>
inline bool inline bool
__valid_range_aux(const _Integral&, const _Integral&, __valid_range_aux(_Integral, _Integral,
typename _Distance_traits<_Integral>::__type& __dist, typename _Distance_traits<_Integral>::__type& __dist,
std::__true_type) std::__true_type)
{ {
...@@ -117,13 +122,12 @@ namespace __gnu_debug ...@@ -117,13 +122,12 @@ namespace __gnu_debug
return true; return true;
} }
/** We have iterators, so figure out what kind of iterators that are /** We have iterators, so figure out what kind of iterators they are
* to see if we can check the range ahead of time. * to see if we can check the range ahead of time.
*/ */
template<typename _InputIterator> template<typename _InputIterator>
inline bool inline bool
__valid_range_aux(const _InputIterator& __first, __valid_range_aux(_InputIterator __first, _InputIterator __last,
const _InputIterator& __last,
typename _Distance_traits<_InputIterator>::__type& __dist, typename _Distance_traits<_InputIterator>::__type& __dist,
std::__false_type) std::__false_type)
{ {
...@@ -152,61 +156,69 @@ namespace __gnu_debug ...@@ -152,61 +156,69 @@ namespace __gnu_debug
*/ */
template<typename _InputIterator> template<typename _InputIterator>
inline bool inline bool
__valid_range(const _InputIterator& __first, const _InputIterator& __last, __valid_range(_InputIterator __first, _InputIterator __last,
typename _Distance_traits<_InputIterator>::__type& __dist) typename _Distance_traits<_InputIterator>::__type& __dist)
{ {
typedef typename std::__is_integer<_InputIterator>::__type _Integral; typedef typename std::__is_integer<_InputIterator>::__type _Integral;
return __valid_range_aux(__first, __last, __dist, _Integral()); return __valid_range_aux(__first, __last, __dist, _Integral());
} }
template<typename _Iterator, typename _Sequence, typename _Category>
bool
__valid_range(const _Safe_iterator<_Iterator, _Sequence, _Category>&,
const _Safe_iterator<_Iterator, _Sequence, _Category>&,
typename _Distance_traits<_Iterator>::__type&);
#if __cplusplus >= 201103L
template<typename _Iterator,typename _Sequence>
bool
__valid_range(const _Safe_local_iterator<_Iterator, _Sequence>&,
const _Safe_local_iterator<_Iterator, _Sequence>&,
typename _Distance_traits<_Iterator>::__type&);
#endif
template<typename _InputIterator> template<typename _InputIterator>
inline bool inline bool
__valid_range(const _InputIterator& __first, const _InputIterator& __last) __valid_range(_InputIterator __first, _InputIterator __last)
{ {
typename _Distance_traits<_InputIterator>::__type __dist; typename _Distance_traits<_InputIterator>::__type __dist;
return __valid_range(__first, __last, __dist); return __valid_range(__first, __last, __dist);
} }
template<typename _Iterator, typename _Sequence, typename _Category>
bool
__valid_range(const _Safe_iterator<_Iterator, _Sequence, _Category>&,
const _Safe_iterator<_Iterator, _Sequence, _Category>&);
#if __cplusplus >= 201103L
template<typename _Iterator, typename _Sequence>
bool
__valid_range(const _Safe_local_iterator<_Iterator, _Sequence>&,
const _Safe_local_iterator<_Iterator, _Sequence>&);
#endif
// Fallback method, always ok. // Fallback method, always ok.
template<typename _InputIterator, typename _Size> template<typename _InputIterator, typename _Size>
inline bool inline bool
__can_advance(_InputIterator, _Size) __can_advance(_InputIterator, _Size)
{ return true; } { return true; }
template<typename _Iterator, typename _Sequence, typename _Size> template<typename _Iterator, typename _Sequence, typename _Category,
typename _Size>
bool bool
__can_advance(const _Safe_iterator<_Iterator, _Sequence>&, _Size); __can_advance(const _Safe_iterator<_Iterator, _Sequence, _Category>&,
_Size);
#if __cplusplus < 201103L
// Helper struct to detect random access safe iterators.
template<typename _Iterator>
struct __is_safe_random_iterator
{
enum { __value = 0 };
typedef std::__false_type __type;
};
template<typename _Iterator>
struct _Siter_base
: std::_Iter_base<_Iterator, __is_safe_random_iterator<_Iterator>::__value>
{ };
/** Helper function to extract base iterator of random access safe iterator /** Helper function to extract base iterator of random access safe iterator
in order to reduce performance impact of debug mode. Limited to random * in order to reduce performance impact of debug mode. Limited to random
access iterator because it is the only category for which it is possible * access iterator because it is the only category for which it is possible
to check for correct iterators order in the __valid_range function * to check for correct iterators order in the __valid_range function
thanks to the < operator. * thanks to the < operator.
*/ */
template<typename _Iterator>
inline typename _Siter_base<_Iterator>::iterator_type
__base(_Iterator __it)
{ return _Siter_base<_Iterator>::_S_base(__it); }
#else
template<typename _Iterator> template<typename _Iterator>
inline _Iterator inline _Iterator
__base(_Iterator __it) __base(_Iterator __it)
{ return __it; } { return __it; }
#endif
#if __cplusplus < 201103L #if __cplusplus < 201103L
template<typename _Iterator> template<typename _Iterator>
......
...@@ -57,6 +57,9 @@ namespace __debug ...@@ -57,6 +57,9 @@ namespace __debug
typedef __gnu_debug::_Equal_to<_Base_const_iterator> _Equal; typedef __gnu_debug::_Equal_to<_Base_const_iterator> _Equal;
typedef __gnu_debug::_Not_equal_to<_Base_const_iterator> _Not_equal; typedef __gnu_debug::_Not_equal_to<_Base_const_iterator> _Not_equal;
template<typename _ItT, typename _SeqT, typename _CatT>
friend class ::__gnu_debug::_Safe_iterator;
public: public:
typedef typename _Base::reference reference; typedef typename _Base::reference reference;
typedef typename _Base::const_reference const_reference; typedef typename _Base::const_reference const_reference;
......
...@@ -56,6 +56,9 @@ namespace __debug ...@@ -56,6 +56,9 @@ namespace __debug
typedef typename _Base::iterator _Base_iterator; typedef typename _Base::iterator _Base_iterator;
typedef __gnu_debug::_Equal_to<_Base_const_iterator> _Equal; typedef __gnu_debug::_Equal_to<_Base_const_iterator> _Equal;
template<typename _ItT, typename _SeqT, typename _CatT>
friend class ::__gnu_debug::_Safe_iterator;
public: public:
// types: // types:
typedef _Key key_type; typedef _Key key_type;
......
...@@ -56,6 +56,9 @@ namespace __debug ...@@ -56,6 +56,9 @@ namespace __debug
typedef typename _Base::iterator _Base_iterator; typedef typename _Base::iterator _Base_iterator;
typedef __gnu_debug::_Equal_to<_Base_const_iterator> _Equal; typedef __gnu_debug::_Equal_to<_Base_const_iterator> _Equal;
template<typename _ItT, typename _SeqT, typename _CatT>
friend class ::__gnu_debug::_Safe_iterator;
public: public:
// types: // types:
typedef _Key key_type; typedef _Key key_type;
......
...@@ -55,6 +55,9 @@ namespace __debug ...@@ -55,6 +55,9 @@ namespace __debug
typedef typename _Base::iterator _Base_iterator; typedef typename _Base::iterator _Base_iterator;
typedef __gnu_debug::_Equal_to<_Base_const_iterator> _Equal; typedef __gnu_debug::_Equal_to<_Base_const_iterator> _Equal;
template<typename _ItT, typename _SeqT, typename _CatT>
friend class ::__gnu_debug::_Safe_iterator;
public: public:
// types: // types:
typedef _Key key_type; typedef _Key key_type;
......
...@@ -31,9 +31,57 @@ ...@@ -31,9 +31,57 @@
namespace __gnu_debug namespace __gnu_debug
{ {
template<typename _Iterator, typename _Sequence> template<typename _Iterator, typename _Sequence, typename _Category>
typename _Distance_traits<_Iterator>::__type
_Safe_iterator<_Iterator, _Sequence, _Category>::
_M_get_distance_from_begin() const
{
typedef _Sequence_traits<_Sequence> _SeqTraits;
// No need to consider before_begin as this function is only used in
// _M_can_advance which won't be used for forward_list iterators.
if (_M_is_begin())
return std::make_pair(0, __dp_exact);
if (_M_is_end())
return _SeqTraits::_S_size(*_M_get_sequence());
typename _Distance_traits<_Iterator>::__type __res
= __get_distance(_M_get_sequence()->_M_base().begin(), base());
if (__res.second == __dp_equality)
return std::make_pair(1, __dp_sign);
return __res;
}
template<typename _Iterator, typename _Sequence, typename _Category>
typename _Distance_traits<_Iterator>::__type
_Safe_iterator<_Iterator, _Sequence, _Category>::
_M_get_distance_to_end() const
{
typedef _Sequence_traits<_Sequence> _SeqTraits;
// No need to consider before_begin as this function is only used in
// _M_can_advance which won't be used for forward_list iterators.
if (_M_is_begin())
return _SeqTraits::_S_size(*_M_get_sequence());
if (_M_is_end())
return std::make_pair(0, __dp_exact);
typename _Distance_traits<_Iterator>::__type __res
= __get_distance(base(), _M_get_sequence()->_M_base().end());
if (__res.second == __dp_equality)
return std::make_pair(1, __dp_sign);
return __res;
}
template<typename _Iterator, typename _Sequence, typename _Category>
bool bool
_Safe_iterator<_Iterator, _Sequence>:: _Safe_iterator<_Iterator, _Sequence, _Category>::
_M_can_advance(const difference_type& __n) const _M_can_advance(const difference_type& __n) const
{ {
if (this->_M_singular()) if (this->_M_singular())
...@@ -45,7 +93,7 @@ namespace __gnu_debug ...@@ -45,7 +93,7 @@ namespace __gnu_debug
if (__n < 0) if (__n < 0)
{ {
std::pair<difference_type, _Distance_precision> __dist = std::pair<difference_type, _Distance_precision> __dist =
__get_distance_from_begin(*this); _M_get_distance_from_begin();
bool __ok = ((__dist.second == __dp_exact && __dist.first >= -__n) bool __ok = ((__dist.second == __dp_exact && __dist.first >= -__n)
|| (__dist.second != __dp_exact && __dist.first > 0)); || (__dist.second != __dp_exact && __dist.first > 0));
return __ok; return __ok;
...@@ -53,16 +101,69 @@ namespace __gnu_debug ...@@ -53,16 +101,69 @@ namespace __gnu_debug
else else
{ {
std::pair<difference_type, _Distance_precision> __dist = std::pair<difference_type, _Distance_precision> __dist =
__get_distance_to_end(*this); _M_get_distance_to_end();
bool __ok = ((__dist.second == __dp_exact && __dist.first >= __n) bool __ok = ((__dist.second == __dp_exact && __dist.first >= __n)
|| (__dist.second != __dp_exact && __dist.first > 0)); || (__dist.second != __dp_exact && __dist.first > 0));
return __ok; return __ok;
} }
} }
template<typename _Iterator, typename _Sequence> template<typename _Iterator, typename _Sequence, typename _Category>
typename _Distance_traits<_Iterator>::__type
_Safe_iterator<_Iterator, _Sequence, _Category>::
_M_get_distance_to(const _Safe_iterator& __rhs) const
{
typedef typename _Distance_traits<_Iterator>::__type _Diff;
typedef _Sequence_traits<_Sequence> _SeqTraits;
if (this->base() == __rhs.base())
return std::make_pair(0, __dp_exact);
if (this->_M_is_before_begin())
{
if (__rhs._M_is_begin())
return std::make_pair(1, __dp_exact);
return std::make_pair(1, __dp_sign);
}
if (this->_M_is_begin())
{
if (__rhs._M_is_before_begin())
return std::make_pair(-1, __dp_exact);
if (__rhs._M_is_end())
return _SeqTraits::_S_size(*this->_M_get_sequence());
return std::make_pair(1, __dp_sign);
}
if (this->_M_is_end())
{
if (__rhs._M_is_before_begin())
return std::make_pair(-1, __dp_exact);
if (__rhs._M_is_begin())
{
_Diff __diff = _SeqTraits::_S_size(*this->_M_get_sequence());
return std::make_pair(-__diff.first, __diff.second);
}
return std::make_pair(-1, __dp_sign);
}
if (__rhs._M_is_before_begin() || __rhs._M_is_begin())
return std::make_pair(-1, __dp_sign);
if (__rhs._M_is_end())
return std::make_pair(1, __dp_sign);
return std::make_pair(1, __dp_equality);
}
template<typename _Iterator, typename _Sequence, typename _Category>
bool bool
_Safe_iterator<_Iterator, _Sequence>:: _Safe_iterator<_Iterator, _Sequence, _Category>::
_M_valid_range(const _Safe_iterator& __rhs, _M_valid_range(const _Safe_iterator& __rhs,
std::pair<difference_type, _Distance_precision>& __dist, std::pair<difference_type, _Distance_precision>& __dist,
bool __check_dereferenceable) const bool __check_dereferenceable) const
...@@ -71,7 +172,7 @@ namespace __gnu_debug ...@@ -71,7 +172,7 @@ namespace __gnu_debug
return false; return false;
/* Determine iterators order */ /* Determine iterators order */
__dist = __get_distance(*this, __rhs); __dist = _M_get_distance_to(__rhs);
switch (__dist.second) switch (__dist.second)
{ {
case __dp_equality: case __dp_equality:
...@@ -90,6 +191,25 @@ namespace __gnu_debug ...@@ -90,6 +191,25 @@ namespace __gnu_debug
// Assume that this is a valid range; we can't check anything else. // Assume that this is a valid range; we can't check anything else.
return true; return true;
} }
template<typename _Iterator, typename _Sequence>
bool
_Safe_iterator<_Iterator, _Sequence, std::random_access_iterator_tag>::
_M_valid_range(const _Safe_iterator& __rhs,
std::pair<difference_type,
_Distance_precision>& __dist) const
{
if (!this->_M_can_compare(__rhs))
return false;
/* Determine iterators order */
__dist = std::make_pair(__rhs.base() - this->base(), __dp_exact);
// If range is not empty first iterator must be dereferenceable.
if (__dist.first > 0)
return this->_M_dereferenceable();
return __dist.first == 0;
}
} // namespace __gnu_debug } // namespace __gnu_debug
#endif #endif
...@@ -51,15 +51,24 @@ namespace __gnu_debug ...@@ -51,15 +51,24 @@ namespace __gnu_debug
{ {
typedef _Iterator _Iter_base; typedef _Iterator _Iter_base;
typedef _Safe_local_iterator_base _Safe_base; typedef _Safe_local_iterator_base _Safe_base;
typedef typename _Sequence::const_local_iterator _Const_local_iterator;
typedef typename _Sequence::size_type size_type; typedef typename _Sequence::size_type size_type;
typedef std::iterator_traits<_Iterator> _Traits; typedef std::iterator_traits<_Iterator> _Traits;
typedef std::__are_same<
typename _Sequence::_Base::const_local_iterator,
_Iterator> _IsConstant;
typedef typename __gnu_cxx::__conditional_type<_IsConstant::__value,
typename _Sequence::_Base::local_iterator,
typename _Sequence::_Base::const_local_iterator>::__type
_OtherIterator;
struct _Attach_single struct _Attach_single
{ }; { };
_Safe_local_iterator(const _Iterator& __i, _Safe_sequence_base* __cont, _Safe_local_iterator(_Iterator __i, _Safe_sequence_base* __cont,
_Attach_single) noexcept _Attach_single) noexcept
: _Iter_base(__i) : _Iter_base(__i)
{ _M_attach_single(__cont); } { _M_attach_single(__cont); }
...@@ -82,8 +91,7 @@ namespace __gnu_debug ...@@ -82,8 +91,7 @@ namespace __gnu_debug
* @pre @p seq is not NULL * @pre @p seq is not NULL
* @post this is not singular * @post this is not singular
*/ */
_Safe_local_iterator(const _Iterator& __i, _Safe_local_iterator(_Iterator __i, const _Safe_sequence_base* __cont)
const _Safe_sequence_base* __cont)
: _Iter_base(__i), _Safe_base(__cont, _S_constant()) : _Iter_base(__i), _Safe_base(__cont, _S_constant())
{ {
_GLIBCXX_DEBUG_VERIFY(!this->_M_singular(), _GLIBCXX_DEBUG_VERIFY(!this->_M_singular(),
...@@ -132,16 +140,15 @@ namespace __gnu_debug ...@@ -132,16 +140,15 @@ namespace __gnu_debug
template<typename _MutableIterator> template<typename _MutableIterator>
_Safe_local_iterator( _Safe_local_iterator(
const _Safe_local_iterator<_MutableIterator, const _Safe_local_iterator<_MutableIterator,
typename __gnu_cxx::__enable_if<std::__are_same< typename __gnu_cxx::__enable_if<_IsConstant::__value &&
_MutableIterator, std::__are_same<_MutableIterator, _OtherIterator>::__value,
typename _Sequence::local_iterator::iterator_type>::__value, _Sequence>::__type>& __x) noexcept
_Sequence>::__type>& __x)
: _Iter_base(__x.base()) : _Iter_base(__x.base())
{ {
// _GLIBCXX_RESOLVE_LIB_DEFECTS // _GLIBCXX_RESOLVE_LIB_DEFECTS
// DR 408. Is vector<reverse_iterator<char*> > forbidden? // DR 408. Is vector<reverse_iterator<char*> > forbidden?
_GLIBCXX_DEBUG_VERIFY(!__x._M_singular() _GLIBCXX_DEBUG_VERIFY(!__x._M_singular()
|| __x.base() == _Iterator(), || __x.base() == _MutableIterator(),
_M_message(__msg_init_const_singular) _M_message(__msg_init_const_singular)
._M_iterator(*this, "this") ._M_iterator(*this, "this")
._M_iterator(__x, "other")); ._M_iterator(__x, "other"));
...@@ -272,12 +279,9 @@ namespace __gnu_debug ...@@ -272,12 +279,9 @@ namespace __gnu_debug
// ------ Utilities ------ // ------ Utilities ------
/// Determine if this is a constant iterator. /// Determine if this is a constant iterator.
static bool static constexpr bool
_S_constant() _S_constant()
{ { return _IsConstant::__value; }
return std::__are_same<_Const_local_iterator,
_Safe_local_iterator>::__value;
}
/** /**
* @brief Return the underlying iterator * @brief Return the underlying iterator
...@@ -326,12 +330,13 @@ namespace __gnu_debug ...@@ -326,12 +330,13 @@ namespace __gnu_debug
std::pair<difference_type, std::pair<difference_type,
_Distance_precision>& __dist_info) const; _Distance_precision>& __dist_info) const;
// Get distance to __rhs.
typename _Distance_traits<_Iterator>::__type
_M_get_distance_to(const _Safe_local_iterator& __rhs) const;
// The sequence this iterator references. // The sequence this iterator references.
typename typename __gnu_cxx::__conditional_type<
__gnu_cxx::__conditional_type<std::__are_same<_Const_local_iterator, _IsConstant::__value, const _Sequence*, _Sequence*>::__type
_Safe_local_iterator>::__value,
const _Sequence*,
_Sequence*>::__type
_M_get_sequence() const _M_get_sequence() const
{ return static_cast<_Sequence*>(_M_sequence); } { return static_cast<_Sequence*>(_M_sequence); }
...@@ -396,7 +401,7 @@ namespace __gnu_debug ...@@ -396,7 +401,7 @@ namespace __gnu_debug
operator!=(const _Safe_local_iterator<_IteratorL, _Sequence>& __lhs, operator!=(const _Safe_local_iterator<_IteratorL, _Sequence>& __lhs,
const _Safe_local_iterator<_IteratorR, _Sequence>& __rhs) const _Safe_local_iterator<_IteratorR, _Sequence>& __rhs)
{ {
_GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(), _GLIBCXX_DEBUG_VERIFY(!__lhs._M_singular() && !__rhs._M_singular(),
_M_message(__msg_iter_compare_bad) _M_message(__msg_iter_compare_bad)
._M_iterator(__lhs, "lhs") ._M_iterator(__lhs, "lhs")
._M_iterator(__rhs, "rhs")); ._M_iterator(__rhs, "rhs"));
...@@ -431,13 +436,6 @@ namespace __gnu_debug ...@@ -431,13 +436,6 @@ namespace __gnu_debug
return __lhs.base() != __rhs.base(); return __lhs.base() != __rhs.base();
} }
/** Safe local iterators know if they are dereferenceable. */
template<typename _Iterator, typename _Sequence>
inline bool
__check_dereferenceable(const _Safe_local_iterator<_Iterator,
_Sequence>& __x)
{ return __x._M_dereferenceable(); }
/** Safe local iterators know how to check if they form a valid range. */ /** Safe local iterators know how to check if they form a valid range. */
template<typename _Iterator, typename _Sequence> template<typename _Iterator, typename _Sequence>
inline bool inline bool
...@@ -446,49 +444,13 @@ namespace __gnu_debug ...@@ -446,49 +444,13 @@ namespace __gnu_debug
typename _Distance_traits<_Iterator>::__type& __dist_info) typename _Distance_traits<_Iterator>::__type& __dist_info)
{ return __first._M_valid_range(__last, __dist_info); } { return __first._M_valid_range(__last, __dist_info); }
/** Safe local iterators need a special method to get distance between each
other. */
template<typename _Iterator, typename _Sequence> template<typename _Iterator, typename _Sequence>
inline std::pair<typename std::iterator_traits<_Iterator>::difference_type, inline bool
_Distance_precision> __valid_range(const _Safe_local_iterator<_Iterator, _Sequence>& __first,
__get_distance(const _Safe_local_iterator<_Iterator, _Sequence>& __first, const _Safe_local_iterator<_Iterator, _Sequence>& __last)
const _Safe_local_iterator<_Iterator, _Sequence>& __last,
std::input_iterator_tag)
{ {
if (__first.base() == __last.base()) typename _Distance_traits<_Iterator>::__type __dist_info;
return { 0, __dp_exact }; return __first._M_valid_range(__last, __dist_info);
if (__first._M_is_begin())
{
if (__last._M_is_end())
return
{
__first._M_get_sequence()->bucket_size(__first.bucket()),
__dp_exact
};
return { 1, __dp_sign };
}
if (__first._M_is_end())
{
if (__last._M_is_begin())
return
{
-__first._M_get_sequence()->bucket_size(__first.bucket()),
__dp_exact
};
return { -1, __dp_sign };
}
if (__last._M_is_begin())
return { -1, __dp_sign };
if (__last._M_is_end())
return { 1, __dp_sign };
return { 1, __dp_equality };
} }
#if __cplusplus < 201103L #if __cplusplus < 201103L
......
...@@ -32,6 +32,47 @@ ...@@ -32,6 +32,47 @@
namespace __gnu_debug namespace __gnu_debug
{ {
template<typename _Iterator, typename _Sequence> template<typename _Iterator, typename _Sequence>
typename _Distance_traits<_Iterator>::__type
_Safe_local_iterator<_Iterator, _Sequence>::
_M_get_distance_to(const _Safe_local_iterator& __rhs) const
{
if (base() == __rhs.base())
return { 0, __dp_exact };
if (_M_is_begin())
{
if (__rhs._M_is_end())
return
{
_M_get_sequence()->bucket_size(bucket()),
__dp_exact
};
return { 1, __dp_sign };
}
if (_M_is_end())
{
if (__rhs._M_is_begin())
return
{
-_M_get_sequence()->bucket_size(bucket()),
__dp_exact
};
return { -1, __dp_sign };
}
if (__rhs._M_is_begin())
return { -1, __dp_sign };
if (__rhs._M_is_end())
return { 1, __dp_sign };
return { 1, __dp_equality };
}
template<typename _Iterator, typename _Sequence>
bool bool
_Safe_local_iterator<_Iterator, _Sequence>:: _Safe_local_iterator<_Iterator, _Sequence>::
_M_valid_range(const _Safe_local_iterator& __rhs, _M_valid_range(const _Safe_local_iterator& __rhs,
...@@ -45,7 +86,7 @@ namespace __gnu_debug ...@@ -45,7 +86,7 @@ namespace __gnu_debug
/* Determine if we can order the iterators without the help of /* Determine if we can order the iterators without the help of
the container */ the container */
__dist = __get_distance(*this, __rhs); __dist = _M_get_distance_to(__rhs);
switch (__dist.second) switch (__dist.second)
{ {
case __dp_equality: case __dp_equality:
......
...@@ -55,6 +55,9 @@ namespace __debug ...@@ -55,6 +55,9 @@ namespace __debug
typedef typename _Base::iterator _Base_iterator; typedef typename _Base::iterator _Base_iterator;
typedef __gnu_debug::_Equal_to<_Base_const_iterator> _Equal; typedef __gnu_debug::_Equal_to<_Base_const_iterator> _Equal;
template<typename _ItT, typename _SeqT, typename _CatT>
friend class ::__gnu_debug::_Safe_iterator;
public: public:
// types: // types:
typedef _Key key_type; typedef _Key key_type;
......
...@@ -52,12 +52,13 @@ namespace __gnu_debug ...@@ -52,12 +52,13 @@ namespace __gnu_debug
__can_advance(const std::reverse_iterator<_Iterator>& __it, _Size __n) __can_advance(const std::reverse_iterator<_Iterator>& __it, _Size __n)
{ return __can_advance(__it.base(), -__n); } { return __can_advance(__it.base(), -__n); }
#if __cplusplus < 201103L template<typename _Iterator, typename _Sequence>
template<typename _Iterator> inline std::reverse_iterator<_Iterator>
struct __is_safe_random_iterator<std::reverse_iterator<_Iterator> > __base(const std::reverse_iterator<_Safe_iterator<
: __is_safe_random_iterator<_Iterator> _Iterator, _Sequence, std::random_access_iterator_tag> >& __it)
{ }; { return std::reverse_iterator<_Iterator>(__it.base().base()); }
#if __cplusplus < 201103L
template<typename _Iterator> template<typename _Iterator>
struct _Unsafe_type<std::reverse_iterator<_Iterator> > struct _Unsafe_type<std::reverse_iterator<_Iterator> >
{ {
...@@ -75,12 +76,6 @@ namespace __gnu_debug ...@@ -75,12 +76,6 @@ namespace __gnu_debug
#else #else
template<typename _Iterator> template<typename _Iterator>
inline auto inline auto
__base(const std::reverse_iterator<_Iterator>& __it)
-> decltype(std::__make_reverse_iterator(__base(__it.base())))
{ return std::__make_reverse_iterator(__base(__it.base())); }
template<typename _Iterator>
inline auto
__unsafe(const std::reverse_iterator<_Iterator>& __it) __unsafe(const std::reverse_iterator<_Iterator>& __it)
-> decltype(std::__make_reverse_iterator(__unsafe(__it.base()))) -> decltype(std::__make_reverse_iterator(__unsafe(__it.base())))
{ return std::__make_reverse_iterator(__unsafe(__it.base())); } { return std::__make_reverse_iterator(__unsafe(__it.base())); }
...@@ -128,7 +123,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -128,7 +123,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_Iterator _Iterator
__niter_base(const __gnu_debug::_Safe_iterator< __niter_base(const __gnu_debug::_Safe_iterator<
__gnu_cxx::__normal_iterator<_Iterator, _Container>, __gnu_cxx::__normal_iterator<_Iterator, _Container>,
_Sequence>&); _Sequence, std::random_access_iterator_tag>&);
_GLIBCXX_END_NAMESPACE_VERSION _GLIBCXX_END_NAMESPACE_VERSION
} }
......
...@@ -94,6 +94,9 @@ namespace __gnu_debug ...@@ -94,6 +94,9 @@ namespace __gnu_debug
basic_string, _Allocator, _Safe_sequence, bool(_GLIBCXX_USE_CXX11_ABI)> basic_string, _Allocator, _Safe_sequence, bool(_GLIBCXX_USE_CXX11_ABI)>
_Safe; _Safe;
template<typename _ItT, typename _SeqT, typename _CatT>
friend class ::__gnu_debug::_Safe_iterator;
public: public:
// types: // types:
typedef _Traits traits_type; typedef _Traits traits_type;
......
...@@ -66,6 +66,11 @@ namespace __debug ...@@ -66,6 +66,11 @@ namespace __debug
_Base_const_local_iterator; _Base_const_local_iterator;
typedef typename _Base::local_iterator _Base_local_iterator; typedef typename _Base::local_iterator _Base_local_iterator;
template<typename _ItT, typename _SeqT, typename _CatT>
friend class ::__gnu_debug::_Safe_iterator;
template<typename _ItT, typename _SeqT>
friend class ::__gnu_debug::_Safe_local_iterator;
public: public:
typedef typename _Base::size_type size_type; typedef typename _Base::size_type size_type;
typedef typename _Base::hasher hasher; typedef typename _Base::hasher hasher;
...@@ -752,6 +757,11 @@ namespace __debug ...@@ -752,6 +757,11 @@ namespace __debug
typedef typename _Base::const_local_iterator _Base_const_local_iterator; typedef typename _Base::const_local_iterator _Base_const_local_iterator;
typedef typename _Base::local_iterator _Base_local_iterator; typedef typename _Base::local_iterator _Base_local_iterator;
template<typename _ItT, typename _SeqT, typename _CatT>
friend class ::__gnu_debug::_Safe_iterator;
template<typename _ItT, typename _SeqT>
friend class ::__gnu_debug::_Safe_local_iterator;
public: public:
typedef typename _Base::size_type size_type; typedef typename _Base::size_type size_type;
typedef typename _Base::hasher hasher; typedef typename _Base::hasher hasher;
...@@ -768,7 +778,7 @@ namespace __debug ...@@ -768,7 +778,7 @@ namespace __debug
typedef __gnu_debug::_Safe_local_iterator< typedef __gnu_debug::_Safe_local_iterator<
_Base_local_iterator, unordered_multimap> local_iterator; _Base_local_iterator, unordered_multimap> local_iterator;
typedef __gnu_debug::_Safe_local_iterator< typedef __gnu_debug::_Safe_local_iterator<
_Base_const_local_iterator, unordered_multimap> const_local_iterator; _Base_const_local_iterator, unordered_multimap> const_local_iterator;
unordered_multimap() = default; unordered_multimap() = default;
......
...@@ -66,6 +66,11 @@ namespace __debug ...@@ -66,6 +66,11 @@ namespace __debug
typedef typename _Base::const_local_iterator _Base_const_local_iterator; typedef typename _Base::const_local_iterator _Base_const_local_iterator;
typedef typename _Base::local_iterator _Base_local_iterator; typedef typename _Base::local_iterator _Base_local_iterator;
template<typename _ItT, typename _SeqT, typename _CatT>
friend class ::__gnu_debug::_Safe_iterator;
template<typename _ItT, typename _SeqT>
friend class ::__gnu_debug::_Safe_local_iterator;
public: public:
typedef typename _Base::size_type size_type; typedef typename _Base::size_type size_type;
typedef typename _Base::hasher hasher; typedef typename _Base::hasher hasher;
...@@ -629,6 +634,11 @@ namespace __debug ...@@ -629,6 +634,11 @@ namespace __debug
_Base_const_local_iterator; _Base_const_local_iterator;
typedef typename _Base::local_iterator _Base_local_iterator; typedef typename _Base::local_iterator _Base_local_iterator;
template<typename _ItT, typename _SeqT, typename _CatT>
friend class ::__gnu_debug::_Safe_iterator;
template<typename _ItT, typename _SeqT>
friend class ::__gnu_debug::_Safe_local_iterator;
public: public:
typedef typename _Base::size_type size_type; typedef typename _Base::size_type size_type;
typedef typename _Base::hasher hasher; typedef typename _Base::hasher hasher;
...@@ -645,7 +655,7 @@ namespace __debug ...@@ -645,7 +655,7 @@ namespace __debug
typedef __gnu_debug::_Safe_local_iterator< typedef __gnu_debug::_Safe_local_iterator<
_Base_local_iterator, unordered_multiset> local_iterator; _Base_local_iterator, unordered_multiset> local_iterator;
typedef __gnu_debug::_Safe_local_iterator< typedef __gnu_debug::_Safe_local_iterator<
_Base_const_local_iterator, unordered_multiset> const_local_iterator; _Base_const_local_iterator, unordered_multiset> const_local_iterator;
unordered_multiset() = default; unordered_multiset() = default;
......
...@@ -127,6 +127,9 @@ namespace __debug ...@@ -127,6 +127,9 @@ namespace __debug
typedef typename _Base::const_iterator _Base_const_iterator; typedef typename _Base::const_iterator _Base_const_iterator;
typedef __gnu_debug::_Equal_to<_Base_const_iterator> _Equal; typedef __gnu_debug::_Equal_to<_Base_const_iterator> _Equal;
template<typename _ItT, typename _SeqT, typename _CatT>
friend class ::__gnu_debug::_Safe_iterator;
public: public:
typedef typename _Base::reference reference; typedef typename _Base::reference reference;
typedef typename _Base::const_reference const_reference; typedef typename _Base::const_reference const_reference;
...@@ -789,7 +792,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -789,7 +792,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_Iterator _Iterator
__niter_base(const __gnu_debug::_Safe_iterator< __niter_base(const __gnu_debug::_Safe_iterator<
__gnu_cxx::__normal_iterator<_Iterator, _Container>, __gnu_cxx::__normal_iterator<_Iterator, _Container>,
_Sequence>& __it) _Sequence, std::random_access_iterator_tag>& __it)
{ return std::__niter_base(__it.base()); } { return std::__niter_base(__it.base()); }
_GLIBCXX_END_NAMESPACE_VERSION _GLIBCXX_END_NAMESPACE_VERSION
......
// Copyright (C) 2018 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
// { dg-do compile { target c++11 } }
#include <list>
void
test01()
{
// A list of int.
const std::list<int> nums = { 1, 2, 3, 4 };
// Grab the iterator type.
using list_itr_type = decltype( std::cbegin( nums ) );
// Confirm cend returns the same type.
static_assert( std::is_same< decltype( std::cend( nums ) ), list_itr_type >::value, "" );
// The list's iterator type provides a well-formed non-member operator-() with valid return type (long int)
using substraction_type
= decltype( std::declval<list_itr_type>() - std::declval<list_itr_type>() ); // { dg-error "no match for 'operator-'" }
}
...@@ -21,31 +21,6 @@ ...@@ -21,31 +21,6 @@
#include <unordered_set> #include <unordered_set>
#include <testsuite_hooks.h> #include <testsuite_hooks.h>
void test01()
{
using namespace __gnu_debug;
std::unordered_set<int> u = { 0, 1, 2 };
VERIFY( __check_dereferenceable(u.begin()) );
auto it = u.begin();
VERIFY( __check_dereferenceable(it) );
VERIFY( __check_dereferenceable(u.cbegin()) );
auto cit = u.begin();
VERIFY( __check_dereferenceable(cit) );
VERIFY( !__check_dereferenceable(u.end()) );
it = u.end();
VERIFY( !__check_dereferenceable(it) );
auto bucket = u.bucket(0);
VERIFY( __check_dereferenceable(u.begin(bucket)) );
auto lit = u.begin(bucket);
VERIFY( __check_dereferenceable(lit) );
VERIFY( !__check_dereferenceable(u.end(bucket)) );
}
void test02() void test02()
{ {
using namespace __gnu_debug; using namespace __gnu_debug;
...@@ -84,7 +59,6 @@ void test02() ...@@ -84,7 +59,6 @@ void test02()
int main() int main()
{ {
test01();
test02(); test02();
return 0; return 0;
} }
...@@ -45,4 +45,4 @@ test02() ...@@ -45,4 +45,4 @@ test02()
// { dg-error "value type is destructible" "" { target *-*-* } 0 } // { dg-error "value type is destructible" "" { target *-*-* } 0 }
// In Debug Mode the "required from here" errors come from <debug/vector> // In Debug Mode the "required from here" errors come from <debug/vector>
// { dg-error "required from here" "" { target *-*-* } 155 } // { dg-error "required from here" "" { target *-*-* } 158 }
...@@ -20,28 +20,6 @@ ...@@ -20,28 +20,6 @@
#include <vector> #include <vector>
#include <testsuite_hooks.h> #include <testsuite_hooks.h>
void test01()
{
using namespace __gnu_debug;
std::vector<int> v1(3, 1);
VERIFY( __check_dereferenceable(v1.begin()) );
std::vector<int>::iterator it = v1.begin();
VERIFY( __check_dereferenceable(it) );
VERIFY( !__check_dereferenceable(v1.end()) );
it = v1.end();
VERIFY( !__check_dereferenceable(it) );
const volatile int* pi = 0;
VERIFY( !__check_dereferenceable(pi) );
int i;
pi = &i;
VERIFY( __check_dereferenceable(pi) );
}
void test02() void test02()
{ {
using namespace __gnu_debug; using namespace __gnu_debug;
...@@ -67,7 +45,6 @@ void test02() ...@@ -67,7 +45,6 @@ void test02()
int main() int main()
{ {
test01();
test02(); test02();
return 0; return 0;
} }
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#ifndef _GLIBCXX_TESTSUITE_CONTAINERS_H #ifndef _GLIBCXX_TESTSUITE_CONTAINERS_H
#define _GLIBCXX_TESTSUITE_CONTAINERS_H #define _GLIBCXX_TESTSUITE_CONTAINERS_H
#include <bits/boost_concept_check.h>
#include <cassert> #include <cassert>
#include <testsuite_container_traits.h> #include <testsuite_container_traits.h>
...@@ -191,6 +192,77 @@ namespace __gnu_test ...@@ -191,6 +192,77 @@ namespace __gnu_test
forward_members_unordered(_Tp& container) { } forward_members_unordered(_Tp& container) { }
}; };
template<typename _Iterator,
bool _Mutable,
typename = typename std::iterator_traits<_Iterator>::iterator_category>
struct iterator_concept_checks;
template<typename _Iterator>
struct iterator_concept_checks<_Iterator, false,
std::forward_iterator_tag>
{
iterator_concept_checks()
{
using namespace __gnu_cxx;
__function_requires<_ForwardIteratorConcept<_Iterator>>();
}
};
template<typename _Iterator>
struct iterator_concept_checks<_Iterator, true,
std::forward_iterator_tag>
{
iterator_concept_checks()
{
using namespace __gnu_cxx;
__function_requires<_Mutable_ForwardIteratorConcept<_Iterator>>();
}
};
template<typename _Iterator>
struct iterator_concept_checks<_Iterator, false,
std::bidirectional_iterator_tag>
{
iterator_concept_checks()
{
using namespace __gnu_cxx;
__function_requires<_BidirectionalIteratorConcept<_Iterator>>();
}
};
template<typename _Iterator>
struct iterator_concept_checks<_Iterator, true,
std::bidirectional_iterator_tag>
{
iterator_concept_checks()
{
using namespace __gnu_cxx;
__function_requires<_Mutable_BidirectionalIteratorConcept<_Iterator>>();
}
};
template<typename _Iterator>
struct iterator_concept_checks<_Iterator, false,
std::random_access_iterator_tag>
{
iterator_concept_checks()
{
using namespace __gnu_cxx;
__function_requires<_RandomAccessIteratorConcept<_Iterator>>();
}
};
template<typename _Iterator>
struct iterator_concept_checks<_Iterator, true,
std::random_access_iterator_tag>
{
iterator_concept_checks()
{
using namespace __gnu_cxx;
__function_requires<_Mutable_RandomAccessIteratorConcept<_Iterator>>();
}
};
template<typename _Tp> template<typename _Tp>
struct citerator struct citerator
{ {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment