PR libstdc++/68222 Hide safe iterator operators

Jonathan Wakely jwakely@redhat.com
Tue Aug 7 13:47:00 GMT 2018


On 02/08/18 22:16 +0200, François Dumont wrote:
>Hi
>
>    Here is a patch to avoid definition of invalid operators on the 
>Debug mode safe iterator type depending on its category.
>
>    Even if it is limited to the Debug mode code I would like to have 
>a feedback before committing. Especially on the following points:
>
>- _Safe_tagged_iterator: Is the name ok ?

Hmm, maybe "strict" instead of tagged?

But do we need a new name? Can we just change _Safe_iterator instead
of adding a new type?

Where is _Safe_iterator still used? Just local iterators in unordered
containers?  Is it OK to remove most of the functions that used to
support it? (__niter_base etc).

Could we add a new type for the local iterators, and just change
_Safe_iterator directly so it doesn't expose unsupported operations?

That would make the patch *much* smaller, as you wouldn't need to
change all the uses of _Safe_iterator.


Another approach would be to use mixins to expose the operations:

template<typename _Iter, typename _Cat>
struct _Safe_iterator_mixin<_Iter, _Cat>
{
  typename iterator_traits<_Iter>::reference
  operator*()
  { return static_cast<_Iter*>(this)->_M_deref(); }
};

template<typename _Iter, typename _Cat>
struct _Safe_iterator_mixin<_Iter, forward_iterator_tag>
{
  _Iter& operator++()
  { return static_cast<_Iter*>(this)->_M_preinc(); }
  _Iter operator++(int)
  { return static_cast<_Iter*>(this)->_M_postinc(); }
};

template<typename _Iter, typename _Cat>
struct _Safe_iterator_mixin<_Iter, bidirectional_iterator_tag>
{
  _Iter& operator--()
  { return static_cast<_Iter*>(this)->_M_predec(); }
  _Iter operator--(int)
  { return static_cast<_Iter*>(this)->_M_postdec(); }
};

etc.

then in _Safe_iterator rename the operator functions, so operator*
becomes _M_deref, operator++ becomes _M_preinc etc. and then derive
from _Safe_iterator_mixin which declares the operators.


>- Inheritance between the different _Safe_tagged_iterator 
>instantiations. I am already working on making the operators friends 
>as we discuss in another thread so I might review this design at this 
>moment.
>
>- Are concept checks I added to testsuite_containers.h citerator ok ?

Yes, they look useful.

>    This patch also does some cleanup on Debug functions. 
>__check_dereferenceable was not used (anymore maybe) so I removed it. 

It would have made the patch a bit more manageable to keep that as a
separate patch, but nevermind.

>diff --git a/libstdc++-v3/include/debug/deque b/libstdc++-v3/include/debug/deque
>index 93b82cf..213e23b 100644
>--- a/libstdc++-v3/include/debug/deque
>+++ b/libstdc++-v3/include/debug/deque
>@@ -57,12 +57,14 @@ namespace __debug
>       typedef __gnu_debug::_Equal_to<_Base_const_iterator> _Equal;
> 
>     public:
>+      typedef _Base					normal_type;

normal_type is not a reserved name, so can't be used.


>diff --git a/libstdc++-v3/include/debug/stl_iterator.h b/libstdc++-v3/include/debug/stl_iterator.h
>index f20b000..fd20160 100644
>--- a/libstdc++-v3/include/debug/stl_iterator.h
>+++ b/libstdc++-v3/include/debug/stl_iterator.h
>@@ -75,12 +76,6 @@ namespace __gnu_debug
> #else
>   template<typename _Iterator>
>     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())); }

This removal doesn't seem to be mentioned in the ChangeLog:

>	* include/debug/stl_iterator.h
>	(__is_safe_random_iterator<std::reverse_iterator<>>): Remove.
>	(__base(const std::reverse_iterator<_Safe_tagged_iterator<_It, _Sq,
>	std::random_access_iterator_tag>)): New overload.



More information about the Libstdc++ mailing list