PR 90409 Deque fiil/copy/move/copy_backward/move_backward/equal overloads
Jonathan Wakely
jwakely@redhat.com
Thu Aug 1 09:57:00 GMT 2019
On 26/07/19 07:06 +0200, François Dumont wrote:
>A new version with tests added at the right place, in 25_algorithms,
>next to the existing basic ones.
>
>Ok to commit ?
Are there any benchmarks showing the performance improvements?
It *should* be faster, but it's a lot of complicated code to add (and
maintain) so it'd better be worth it.
More comments inline below ...
>François
>
>On 6/19/19 7:32 PM, François Dumont wrote:
>>I wanted to implement Debug overloads for those already existing
>>overloads but then realized that those algos could be generalized.
>>This way we will benefit from the memmove replacement when operating
>>with C array or std::array or std::vector iterators.
>>
>>I might do the same for lexicographical_compare one day.
>>
>>The ChangeLog below is quite huge so I attached it. I wonder if I
>>could use deque::iterator and deque::const_iterator in place of the
>>_Deque_iterator<> to reduce it ?
>>
>>Tested under Linux x86_64 normal and debug modes, ok to commit ?
>>
>>François
>>
>
>diff --git a/libstdc++-v3/include/bits/deque.tcc b/libstdc++-v3/include/bits/deque.tcc
>index 3f77b4f079c..9db869fb666 100644
>--- a/libstdc++-v3/include/bits/deque.tcc
>+++ b/libstdc++-v3/include/bits/deque.tcc
>@@ -967,155 +967,507 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
> this->_M_impl._M_finish._M_set_node(__new_nstart + __old_num_nodes - 1);
> }
>
>+_GLIBCXX_END_NAMESPACE_CONTAINER
>+
> // Overload for deque::iterators, exploiting the "segmented-iterator
> // optimization".
> template<typename _Tp>
> void
>- fill(const _Deque_iterator<_Tp, _Tp&, _Tp*>& __first,
>- const _Deque_iterator<_Tp, _Tp&, _Tp*>& __last, const _Tp& __value)
>+ fill(const _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Tp&, _Tp*>& __first,
>+ const _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Tp&, _Tp*>& __last,
>+ const _Tp& __value)
> {
>- typedef typename _Deque_iterator<_Tp, _Tp&, _Tp*>::_Self _Self;
>-
>- for (typename _Self::_Map_pointer __node = __first._M_node + 1;
>- __node < __last._M_node; ++__node)
>- std::fill(*__node, *__node + _Self::_S_buffer_size(), __value);
>+ typedef typename _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Tp&, _Tp*>::_Self
>+ _Self;
I know it was already there, but this is a terrible name. Using
"_Self" inside a class to refer to the class type itself is OK, but
using it outside the class doesn't make sense.
And anyway, isn't _Deque_iterator<T, T&, T*>::_Self just the same type as
_Deque_iterator<T, T&, T*> ? It should be something like:
typedef typename _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Tp&, _Tp*> _Iter;
>+ template<typename _II, typename _Tp>
>+ typename enable_if<
>+ is_same<typename std::iterator_traits<_II>::iterator_category,
>+ std::random_access_iterator_tag>::value,
Use is_base_of<random_access_iterator_tag, ...::iterator_category> so
it works for types derived from random_access_iterator_tag too.
>+ _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Tp&, _Tp*> >::type
>+ move(_II __first, _II __last,
>+ _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Tp&, _Tp*> __result)
>+ {
>+ __glibcxx_requires_can_increment_range(__first, __last, __result);
>
>- if (!__llen)
>- {
>- __llen = _Self::_S_buffer_size();
>- __lend = *(__last._M_node - 1) + __llen;
>- }
>- if (!__rlen)
>- {
>- __rlen = _Self::_S_buffer_size();
>- __rend = *(__result._M_node - 1) + __rlen;
>- }
>+ return __detail::__move_to_dit(__first, __last, __result);
>+ }
>
>- const difference_type __clen = std::min(__len,
>- std::min(__llen, __rlen));
>- std::move_backward(__lend - __clen, __lend, __rend);
>- __last -= __clen;
>- __result -= __clen;
>- __len -= __clen;
>- }
>- return __result;
>+ template<typename _Tp, typename _OI>
>+ _OI
>+ move_backward(
>+ _GLIBCXX_STD_C::_Deque_iterator<_Tp, const _Tp&, const _Tp*> __first,
>+ _GLIBCXX_STD_C::_Deque_iterator<_Tp, const _Tp&, const _Tp*> __last,
>+ _OI __result)
>+ {
>+ __glibcxx_requires_can_decrement_range(__first, __last, __result);
>+
>+ return __detail::__move_backward_from_dit(__first, __last, __result);
>+ }
>+
>+ template<typename _Tp>
>+ _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Tp&, _Tp*>
>+ move_backward(
>+ _GLIBCXX_STD_C::_Deque_iterator<_Tp, const _Tp&, const _Tp*> __first,
>+ _GLIBCXX_STD_C::_Deque_iterator<_Tp, const _Tp&, const _Tp*> __last,
>+ _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Tp&, _Tp*> __result)
>+ {
>+ __glibcxx_requires_can_decrement_range(__first, __last, __result);
>+
>+ return __detail::__move_backward_from_dit(__first, __last, __result);
>+ }
>+
>+ template<typename _II, typename _Tp>
>+ typename enable_if<
>+ is_same<typename std::iterator_traits<_II>::iterator_category,
>+ std::random_access_iterator_tag>::value,
Here as well.
>+ _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Tp&, _Tp*> >::type
>+ move_backward(_II __first, _II __last,
>+ _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Tp&, _Tp*> __result)
>+ {
>+ __glibcxx_requires_can_decrement_range(__first, __last, __result);
>+
>+ return __detail::__move_backward_to_dit(__first, __last, __result);
> }
> #endif
Please add "// C++11" after the #endif that corresponds to a
__cplusplus check. In general every #endif should have a ocmment,
unless the distance between the #if and the #endif is only a few
lines.
>+ template<typename _Tp, typename _OI>
>+ inline _OI
>+ copy(_GLIBCXX_STD_C::_Deque_iterator<_Tp, _Tp&, _Tp*> __first,
>+ _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Tp&, _Tp*> __last,
>+ _OI __result)
>+ {
>+ return std::copy(
>+ _GLIBCXX_STD_C::_Deque_iterator<_Tp, const _Tp&, const _Tp*>(__first),
>+ _GLIBCXX_STD_C::_Deque_iterator<_Tp, const _Tp&, const _Tp*>(__last),
>+ __result);
I think this would be easier to read as:
{
typedef _GLIBCXX_STD_C::_Deque_iterator<_Tp, const _Tp&, const _Tp*>
_Citer;
return std::copy(_Citer(__first), _Citer(__last), __result);
>+ template<typename _II, typename _Tp>
>+ typename __gnu_cxx::__enable_if<
>+ __are_same<typename std::iterator_traits<_II>::iterator_category,
>+ std::random_access_iterator_tag>::__value,
This won't work for iterator categories derived from
random_access_iterator_tag. Tag dispatching would work.
>+#endif
Please add "// C++11" after the #endif
More information about the Gcc-patches
mailing list