P0646R1 Improving the Return Value of Erase-Like Algorithms I

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

	P0646R1 Improving the Return Value of Erase-Like Algorithms I
	* include/debug/forward_list (forward_list::__remove_return_type):
	Define typedef as size_type or void, according to __cplusplus value.
	(_GLIBCXX_FWDLIST_REMOVE_RETURN_TYPE_TAG): Define macro as abi-tag or
	empty, according to __cplusplus value.
	(_GLIBCXX20_ONLY): Define macro.
	(forward_list::remove, forward_list::unique): Use typedef and macro
	to change return type and add abi-tag for C++2a. Return number of
	removed elements for C++2a.
	(forward_list::remove_if<Pred>, forward_list::unique<BinPred>): Use
	typedef to change return type for C++2a. Return number of removed
	elements for C++2a.
	* include/debug/list (list::__remove_return_type): Define typedef as
	size_type or void, according to __cplusplus value.
	(_GLIBCXX_LIST_REMOVE_RETURN_TYPE_TAG): Define macro as abi-tag or
	empty, according to __cplusplus value.
	(_GLIBCXX20_ONLY): Define macro.
	(list::remove, list::unique): Use typedef and macro to change return
	type and add abi-tag for C++2a. Return number of removed elements for
	C++2a.
	(list::remove_if<Predicate>, list::unique<BinaryPredicate>): Use typedef
	to change return type for C++2a. Return number of removed elements for
	C++2a.

From-SVN: r263752
This commit is contained in:
François Dumont 2018-08-21 19:44:41 +00:00
parent fa3d2d3810
commit f7191a37ee
3 changed files with 199 additions and 61 deletions

View File

@ -1,3 +1,29 @@
2018-08-21 François Dumont <fdumont@gcc.gnu.org>
P0646R1 Improving the Return Value of Erase-Like Algorithms I
* include/debug/forward_list (forward_list::__remove_return_type):
Define typedef as size_type or void, according to __cplusplus value.
(_GLIBCXX_FWDLIST_REMOVE_RETURN_TYPE_TAG): Define macro as abi-tag or
empty, according to __cplusplus value.
(_GLIBCXX20_ONLY): Define macro.
(forward_list::remove, forward_list::unique): Use typedef and macro
to change return type and add abi-tag for C++2a. Return number of
removed elements for C++2a.
(forward_list::remove_if<Pred>, forward_list::unique<BinPred>): Use
typedef to change return type for C++2a. Return number of removed
elements for C++2a.
* include/debug/list (list::__remove_return_type): Define typedef as
size_type or void, according to __cplusplus value.
(_GLIBCXX_LIST_REMOVE_RETURN_TYPE_TAG): Define macro as abi-tag or
empty, according to __cplusplus value.
(_GLIBCXX20_ONLY): Define macro.
(list::remove, list::unique): Use typedef and macro to change return
type and add abi-tag for C++2a. Return number of removed elements for
C++2a.
(list::remove_if<Predicate>, list::unique<BinaryPredicate>): Use typedef
to change return type for C++2a. Return number of removed elements for
C++2a.
2018-08-21 David Edelsohn <dje.gcc@gmail.com> 2018-08-21 David Edelsohn <dje.gcc@gmail.com>
* testsuite/18_support/new_nothrow.cc: XFAIL on AIX. * testsuite/18_support/new_nothrow.cc: XFAIL on AIX.

View File

@ -653,70 +653,113 @@ namespace __debug
const_iterator __before, const_iterator __last) const_iterator __before, const_iterator __last)
{ splice_after(__pos, std::move(__list), __before, __last); } { splice_after(__pos, std::move(__list), __before, __last); }
void private:
#if __cplusplus > 201703L
using __remove_return_type = size_type;
# define _GLIBCXX_FWDLIST_REMOVE_RETURN_TYPE_TAG \
__attribute__((__abi_tag__("__cxx20")))
# define _GLIBCXX20_ONLY(__expr) __expr
#else
using __remove_return_type = void;
# define _GLIBCXX_FWDLIST_REMOVE_RETURN_TYPE_TAG
# define _GLIBCXX20_ONLY(__expr)
#endif
public:
_GLIBCXX_FWDLIST_REMOVE_RETURN_TYPE_TAG
__remove_return_type
remove(const _Tp& __val) remove(const _Tp& __val)
{ {
if (!this->_M_iterators && !this->_M_const_iterators)
return _Base::remove(__val);
size_type __removed __attribute__((__unused__)) = 0;
_Base_iterator __x = _Base::before_begin(); _Base_iterator __x = _Base::before_begin();
_Base_iterator __old = __x++; _Base_iterator __old = __x++;
_Base_iterator __extra = _Base::end();
while (__x != _Base::end()) while (__x != _Base::end())
{ {
if (*__x == __val) if (*__x == __val)
__x = _M_erase_after(__old); {
else if (std::__addressof(*__x) != std::__addressof(__val))
__old = __x++; {
__x = _M_erase_after(__old);
_GLIBCXX20_ONLY( __removed++ );
continue;
}
else
__extra = __old;
}
__old = __x++;
} }
if (__extra != _Base::end())
{
this->_M_erase_after(__extra);
_GLIBCXX20_ONLY( __removed++ );
}
return _GLIBCXX20_ONLY( __removed );
} }
template<typename _Pred> template<typename _Pred>
void __remove_return_type
remove_if(_Pred __pred) remove_if(_Pred __pred)
{ {
if (!this->_M_iterators && !this->_M_const_iterators)
return _Base::remove_if(__pred);
size_type __removed __attribute__((__unused__)) = 0;
_Base_iterator __x = _Base::before_begin(); _Base_iterator __x = _Base::before_begin();
_Base_iterator __old = __x++; _Base_iterator __old = __x++;
while (__x != _Base::end()) while (__x != _Base::end())
{ if (__pred(*__x))
if (__pred(*__x)) {
__x = _M_erase_after(__old); __x = _M_erase_after(__old);
else _GLIBCXX20_ONLY( __removed++ );
__old = __x++; }
} else
__old = __x++;
return _GLIBCXX20_ONLY( __removed );
} }
void _GLIBCXX_FWDLIST_REMOVE_RETURN_TYPE_TAG
__remove_return_type
unique() unique()
{ { return unique(std::equal_to<_Tp>()); }
_Base_iterator __first = _Base::begin();
_Base_iterator __last = _Base::end();
if (__first == __last)
return;
_Base_iterator __next = std::next(__first);
while (__next != __last)
{
if (*__first == *__next)
__next = _M_erase_after(__first);
else
__first = __next++;
}
}
template<typename _BinPred> template<typename _BinPred>
void __remove_return_type
unique(_BinPred __binary_pred) unique(_BinPred __binary_pred)
{ {
if (!this->_M_iterators && !this->_M_const_iterators)
return _Base::unique(__binary_pred);
_Base_iterator __first = _Base::begin(); _Base_iterator __first = _Base::begin();
_Base_iterator __last = _Base::end(); _Base_iterator __last = _Base::end();
if (__first == __last) if (__first == __last)
return; return _GLIBCXX20_ONLY(0);
size_type __removed __attribute__((__unused__)) = 0;
_Base_iterator __next = std::next(__first); _Base_iterator __next = std::next(__first);
while (__next != __last) while (__next != __last)
{ {
if (__binary_pred(*__first, *__next)) if (__binary_pred(*__first, *__next))
__next = _M_erase_after(__first); {
__next = _M_erase_after(__first);
_GLIBCXX20_ONLY( __removed++ );
}
else else
__first = __next++; __first = __next++;
} }
return _GLIBCXX20_ONLY( __removed );
} }
#undef _GLIBCXX_FWDLIST_REMOVE_RETURN_TYPE_TAG
#undef _GLIBCXX20_ONLY
void void
merge(forward_list&& __list) merge(forward_list&& __list)
{ {

View File

@ -641,66 +641,135 @@ namespace __debug
{ splice(__position, std::move(__x), __first, __last); } { splice(__position, std::move(__x), __first, __last); }
#endif #endif
void private:
#if __cplusplus > 201703L
typedef size_type __remove_return_type;
# define _GLIBCXX_LIST_REMOVE_RETURN_TYPE_TAG \
__attribute__((__abi_tag__("__cxx20")))
# define _GLIBCXX20_ONLY(__expr) __expr
#else
typedef void __remove_return_type;
# define _GLIBCXX_LIST_REMOVE_RETURN_TYPE_TAG
# define _GLIBCXX20_ONLY(__expr)
#endif
public:
_GLIBCXX_LIST_REMOVE_RETURN_TYPE_TAG
__remove_return_type
remove(const _Tp& __value) remove(const _Tp& __value)
{ {
for (_Base_iterator __x = _Base::begin(); __x != _Base::end(); ) if (!this->_M_iterators && !this->_M_const_iterators)
return _Base::remove(__value);
size_type __removed __attribute__((__unused__)) = 0;
_Base_iterator __first = _Base::begin();
_Base_iterator __last = _Base::end();
_Base_iterator __extra = __last;
while (__first != __last)
{ {
if (*__x == __value) if (*__first == __value)
__x = _M_erase(__x); // _GLIBCXX_RESOLVE_LIB_DEFECTS
// 526. Is it undefined if a function in the standard changes
// in parameters?
if (std::__addressof(*__first) != std::__addressof(__value))
{
__first = _M_erase(__first);
_GLIBCXX20_ONLY( __removed++ );
}
else
{
__extra = __first;
++__first;
}
else else
++__x; ++__first;
} }
if (__extra != __last)
{
_M_erase(__extra);
_GLIBCXX20_ONLY( __removed++ );
}
return _GLIBCXX20_ONLY( __removed );
} }
template<class _Predicate> template<class _Predicate>
void __remove_return_type
remove_if(_Predicate __pred) remove_if(_Predicate __pred)
{ {
if (!this->_M_iterators && !this->_M_const_iterators)
return _Base::remove_if(__pred);
size_type __removed __attribute__((__unused__)) = 0;
for (_Base_iterator __x = _Base::begin(); __x != _Base::end(); ) for (_Base_iterator __x = _Base::begin(); __x != _Base::end(); )
{ if (__pred(*__x))
if (__pred(*__x)) {
__x = _M_erase(__x); __x = _M_erase(__x);
else _GLIBCXX20_ONLY( __removed++ );
++__x; }
} else
++__x;
return _GLIBCXX20_ONLY( __removed );
} }
void _GLIBCXX_LIST_REMOVE_RETURN_TYPE_TAG
__remove_return_type
unique() unique()
{ {
if (!this->_M_iterators && !this->_M_const_iterators)
return _Base::unique();
if (empty())
return _GLIBCXX20_ONLY(0);
size_type __removed __attribute__((__unused__)) = 0;
_Base_iterator __first = _Base::begin(); _Base_iterator __first = _Base::begin();
_Base_iterator __last = _Base::end(); _Base_iterator __last = _Base::end();
if (__first == __last) _Base_iterator __next = __first;
return; while (++__next != __last)
_Base_iterator __next = __first; ++__next; if (*__first == *__next)
while (__next != __last) {
{ _M_erase(__next);
if (*__first == *__next) __next = __first;
__next = _M_erase(__next); _GLIBCXX20_ONLY( __removed++ );
else }
__first = __next++; else
} __first = __next;
return _GLIBCXX20_ONLY( __removed );
} }
template<class _BinaryPredicate> template<class _BinaryPredicate>
void __remove_return_type
unique(_BinaryPredicate __binary_pred) unique(_BinaryPredicate __binary_pred)
{ {
if (!this->_M_iterators && !this->_M_const_iterators)
return _Base::unique(__binary_pred);
if (empty())
return _GLIBCXX20_ONLY(0);
size_type __removed __attribute__((__unused__)) = 0;
_Base_iterator __first = _Base::begin(); _Base_iterator __first = _Base::begin();
_Base_iterator __last = _Base::end(); _Base_iterator __last = _Base::end();
if (__first == __last) _Base_iterator __next = __first;;
return; while (++__next != __last)
_Base_iterator __next = __first; ++__next; if (__binary_pred(*__first, *__next))
while (__next != __last) {
{ _M_erase(__next);
if (__binary_pred(*__first, *__next)) __next = __first;
__next = _M_erase(__next); _GLIBCXX20_ONLY( __removed++ );
else }
__first = __next++; else
} __first = __next;
return _GLIBCXX20_ONLY( __removed );
} }
#undef _GLIBCXX_LIST_REMOVE_RETURN_TYPE_TAG
#undef _GLIBCXX20_ONLY
void void
#if __cplusplus >= 201103L #if __cplusplus >= 201103L
merge(list&& __x) merge(list&& __x)