re PR libstdc++/61347 (std::distance(list.first(),list.end()) in O(1))

2015-04-14  Marc Glisse  <marc.glisse@inria.fr>

	PR libstdc++/61347
	* include/bits/stl_iterator_base_funcs.h (_List_iterator,
	_List_const_iterator): Declare.
	(__distance): Declare new overloads for _List_iterator and
	_List_const_iterator.
	* include/bits/stl_list.h (__distance): New overloads for
	_List_iterator and _List_const_iterator.
	* testsuite/23_containers/list/61347.cc: New testcase.

From-SVN: r222082
This commit is contained in:
Marc Glisse 2015-04-14 13:02:48 +02:00 committed by Marc Glisse
parent 453e2916ce
commit 194571f10e
4 changed files with 120 additions and 0 deletions

View File

@ -1,3 +1,14 @@
2015-04-14 Marc Glisse <marc.glisse@inria.fr>
PR libstdc++/61347
* include/bits/stl_iterator_base_funcs.h (_List_iterator,
_List_const_iterator): Declare.
(__distance): Declare new overloads for _List_iterator and
_List_const_iterator.
* include/bits/stl_list.h (__distance): New overloads for
_List_iterator and _List_const_iterator.
* testsuite/23_containers/list/61347.cc: New testcase.
2015-04-14 Jonathan Wakely <jwakely@redhat.com> 2015-04-14 Jonathan Wakely <jwakely@redhat.com>
* doc/xml/manual/evolution.xml: Fix typos. * doc/xml/manual/evolution.xml: Fix typos.

View File

@ -66,6 +66,12 @@
namespace std _GLIBCXX_VISIBILITY(default) namespace std _GLIBCXX_VISIBILITY(default)
{ {
_GLIBCXX_BEGIN_NAMESPACE_CONTAINER
// Forward declaration for the overloads of __distance.
template <typename> struct _List_iterator;
template <typename> struct _List_const_iterator;
_GLIBCXX_END_NAMESPACE_CONTAINER
_GLIBCXX_BEGIN_NAMESPACE_VERSION _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _InputIterator> template<typename _InputIterator>
@ -96,6 +102,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return __last - __first; return __last - __first;
} }
#if _GLIBCXX_USE_CXX11_ABI
// Forward declaration because of the qualified call in distance.
template<typename _Tp>
ptrdiff_t
__distance(_GLIBCXX_STD_C::_List_iterator<_Tp>,
_GLIBCXX_STD_C::_List_iterator<_Tp>,
input_iterator_tag);
template<typename _Tp>
ptrdiff_t
__distance(_GLIBCXX_STD_C::_List_const_iterator<_Tp>,
_GLIBCXX_STD_C::_List_const_iterator<_Tp>,
input_iterator_tag);
#endif
/** /**
* @brief A generalization of pointer arithmetic. * @brief A generalization of pointer arithmetic.
* @param __first An input iterator. * @param __first An input iterator.

View File

@ -1868,6 +1868,45 @@ _GLIBCXX_END_NAMESPACE_CXX11
{ __x.swap(__y); } { __x.swap(__y); }
_GLIBCXX_END_NAMESPACE_CONTAINER _GLIBCXX_END_NAMESPACE_CONTAINER
#if _GLIBCXX_USE_CXX11_ABI
_GLIBCXX_BEGIN_NAMESPACE_VERSION
// Detect when distance is used to compute the size of the whole list.
template<typename _Tp>
inline ptrdiff_t
__distance(_GLIBCXX_STD_C::_List_iterator<_Tp> __first,
_GLIBCXX_STD_C::_List_iterator<_Tp> __last,
input_iterator_tag __tag)
{
typedef _GLIBCXX_STD_C::_List_const_iterator<_Tp> _CIter;
return std::__distance(_CIter(__first), _CIter(__last), __tag);
}
template<typename _Tp>
inline ptrdiff_t
__distance(_GLIBCXX_STD_C::_List_const_iterator<_Tp> __first,
_GLIBCXX_STD_C::_List_const_iterator<_Tp> __last,
input_iterator_tag)
{
typedef _GLIBCXX_STD_C::_List_node<size_t> _Sentinel;
_GLIBCXX_STD_C::_List_const_iterator<_Tp> __beyond = __last;
++__beyond;
bool __whole = __first == __beyond;
if (__builtin_constant_p (__whole) && __whole)
return static_cast<const _Sentinel*>(__last._M_node)->_M_data;
ptrdiff_t __n = 0;
while (__first != __last)
{
++__first;
++__n;
}
return __n;
}
_GLIBCXX_END_NAMESPACE_VERSION
#endif
} // namespace std } // namespace std
#endif /* _STL_LIST_H */ #endif /* _STL_LIST_H */

View File

@ -0,0 +1,49 @@
// { dg-options "-std=gnu++11 -O2 -D_GLIBCXX_USE_CXX11_ABI" }
// Copyright (C) 2015 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/>.
#include <list>
#include <iterator>
#include <testsuite_hooks.h>
__attribute__((__noinline__, __noclone__))
void testm(std::list<short>& l)
{
bool b = std::distance(l.begin(), l.end()) == l.size();
VERIFY( __builtin_constant_p(b) );
VERIFY( b );
}
__attribute__((__noinline__, __noclone__))
void testc(const std::list<short>& l)
{
bool b = std::distance(l.begin(), l.end()) == l.size();
VERIFY( __builtin_constant_p(b) );
VERIFY( b );
}
int main()
{
bool test __attribute__((unused)) = true;
#if _GLIBCXX_USE_DUAL_ABI
std::list<short> l;
testm(l);
testc(l);
#endif
}