Index: include/forward_list =================================================================== --- include/forward_list +++ include/forward_list @@ -821,11 +821,11 @@ void splice_after(const_iterator __p, forward_list& __x, const_iterator __i); void splice_after(const_iterator __p, forward_list& __x, const_iterator __f, const_iterator __l); - void remove(const value_type& __v); - template void remove_if(_Predicate __pred); + size_type remove(const value_type& __v); + template size_type remove_if(_Predicate __pred); _LIBCPP_INLINE_VISIBILITY - void unique() {unique(__equal_to());} - template void unique(_BinaryPredicate __binary_pred); + size_type unique() {return unique(__equal_to());} + template size_type unique(_BinaryPredicate __binary_pred); #ifndef _LIBCPP_CXX03_LANG _LIBCPP_INLINE_VISIBILITY void merge(forward_list&& __x) {merge(__x, __less());} @@ -1502,18 +1502,19 @@ #endif // _LIBCPP_CXX03_LANG template -void +typename forward_list<_Tp, _Alloc>::size_type forward_list<_Tp, _Alloc>::remove(const value_type& __v) { forward_list<_Tp, _Alloc> __deleted_nodes; // collect the nodes we're removing + typename forward_list<_Tp, _Alloc>::size_type __count_removed = 0; iterator __e = end(); for (iterator __i = before_begin(); __i.__get_begin()->__next_ != nullptr;) { if (__i.__get_begin()->__next_->__value_ == __v) { iterator __j = _VSTD::next(__i, 2); - for (; __j != __e && *__j == __v; ++__j) - ; + for (++__count_removed; __j != __e && *__j == __v; ++__j) + ++__count_removed; __deleted_nodes.splice_after(__deleted_nodes.before_begin(), *this, __i, __j); if (__j == __e) break; @@ -1522,21 +1523,24 @@ else ++__i; } + + return __count_removed; } template template -void +typename forward_list<_Tp, _Alloc>::size_type forward_list<_Tp, _Alloc>::remove_if(_Predicate __pred) { iterator __e = end(); + typename forward_list<_Tp, _Alloc>::size_type __count_removed = 0; for (iterator __i = before_begin(); __i.__get_begin()->__next_ != nullptr;) { if (__pred(__i.__get_begin()->__next_->__value_)) { iterator __j = _VSTD::next(__i, 2); - for (; __j != __e && __pred(*__j); ++__j) - ; + for (++__count_removed; __j != __e && __pred(*__j); ++__j) + ++__count_removed; erase_after(__i, __j); if (__j == __e) break; @@ -1545,22 +1549,27 @@ else ++__i; } + + return __count_removed; } template template -void +typename forward_list<_Tp, _Alloc>::size_type forward_list<_Tp, _Alloc>::unique(_BinaryPredicate __binary_pred) { + typename forward_list<_Tp, _Alloc>::size_type __count_removed = 0; for (iterator __i = begin(), __e = end(); __i != __e;) { iterator __j = _VSTD::next(__i); for (; __j != __e && __binary_pred(*__i, *__j); ++__j) - ; + ++__count_removed; if (__i.__get_begin()->__next_ != __j.__get_unsafe_node_pointer()) erase_after(__i, __j); __i = __j; } + + return __count_removed; } template Index: include/list =================================================================== --- include/list +++ include/list @@ -1070,12 +1070,12 @@ void splice(const_iterator __p, list& __c, const_iterator __i); void splice(const_iterator __p, list& __c, const_iterator __f, const_iterator __l); - void remove(const value_type& __x); - template void remove_if(_Pred __pred); + size_type remove(const value_type& __x); + template size_type remove_if(_Pred __pred); _LIBCPP_INLINE_VISIBILITY - void unique(); + size_type unique(); template - void unique(_BinaryPred __binary_pred); + size_type unique(_BinaryPred __binary_pred); _LIBCPP_INLINE_VISIBILITY void merge(list& __c); #ifndef _LIBCPP_CXX03_LANG @@ -2141,7 +2141,7 @@ } template -void +typename list<_Tp, _Alloc>::size_type list<_Tp, _Alloc>::remove(const value_type& __x) { list<_Tp, _Alloc> __deleted_nodes(get_allocator()); // collect the nodes we're removing @@ -2160,13 +2160,16 @@ else ++__i; } + + return __deleted_nodes.size(); } template template -void +typename list<_Tp, _Alloc>::size_type list<_Tp, _Alloc>::remove_if(_Pred __pred) { + typename list<_Tp, _Alloc>::size_type __start_size = size(); for (iterator __i = begin(), __e = end(); __i != __e;) { if (__pred(*__i)) @@ -2180,22 +2183,24 @@ } else ++__i; - } + } + return __start_size - size(); } template inline -void +typename list<_Tp, _Alloc>::size_type list<_Tp, _Alloc>::unique() { - unique(__equal_to()); + return unique(__equal_to()); } template template -void +typename list<_Tp, _Alloc>::size_type list<_Tp, _Alloc>::unique(_BinaryPred __binary_pred) { + typename list<_Tp, _Alloc>::size_type __start_size = size(); for (iterator __i = begin(), __e = end(); __i != __e;) { iterator __j = _VSTD::next(__i); @@ -2204,6 +2209,8 @@ if (++__i != __j) __i = erase(__i, __j); } + + return __start_size - size(); } template Index: test/libcxx/diagnostics/nodiscard_extensions.fail.cpp =================================================================== --- test/libcxx/diagnostics/nodiscard_extensions.fail.cpp +++ test/libcxx/diagnostics/nodiscard_extensions.fail.cpp @@ -12,6 +12,10 @@ // GCC versions prior to 7.0 don't provide the required [[nodiscard]] attribute. // UNSUPPORTED: gcc-4, gcc-5, gcc-6 +// AppleClang9 doesn't yet support C++17's implicitly synthesized deduction +// guides from existing ctors, needed by default_searcher() below. +// UNSUPPORTED: apple-clang-9 + // Test that entities declared [[nodiscard]] as at extension by libc++, are // only actually declared such when _LIBCPP_ENABLE_NODISCARD is specified. Index: test/libcxx/diagnostics/nodiscard_extensions.pass.cpp =================================================================== --- test/libcxx/diagnostics/nodiscard_extensions.pass.cpp +++ test/libcxx/diagnostics/nodiscard_extensions.pass.cpp @@ -13,6 +13,10 @@ // This test intentionally leaks memory, so it is unsupported under ASAN. // UNSUPPORTED: asan +// AppleClang9 doesn't yet support C++17's implicitly synthesized deduction +// guides from existing ctors, needed by default_searcher() below. +// UNSUPPORTED: apple-clang-9 + // All entities to which libc++ applies [[nodiscard]] as an extension should // be tested here and in nodiscard_extensions.fail.cpp. They should also // be listed in `UsingLibcxx.rst` in the documentation for the extension. Index: test/std/containers/sequences/forwardlist/forwardlist.ops/remove.pass.cpp =================================================================== --- test/std/containers/sequences/forwardlist/forwardlist.ops/remove.pass.cpp +++ test/std/containers/sequences/forwardlist/forwardlist.ops/remove.pass.cpp @@ -36,7 +36,7 @@ const T t2[] = {5, 5, 5}; C c1(std::begin(t1), std::end(t1)); C c2(std::begin(t2), std::end(t2)); - c1.remove(0); + assert(c1.remove(0) == 4); assert(c1 == c2); } { @@ -45,7 +45,7 @@ const T t1[] = {0, 0, 0, 0}; C c1(std::begin(t1), std::end(t1)); C c2; - c1.remove(0); + assert(c1.remove(0) == 4); assert(c1 == c2); } { @@ -55,7 +55,7 @@ const T t2[] = {5, 5, 5}; C c1(std::begin(t1), std::end(t1)); C c2(std::begin(t2), std::end(t2)); - c1.remove(0); + assert(c1.remove(0) == 0); assert(c1 == c2); } { @@ -63,7 +63,7 @@ typedef std::forward_list C; C c1; C c2; - c1.remove(0); + assert(c1.remove(0) == 0); assert(c1 == c2); } { @@ -73,7 +73,7 @@ const T t2[] = {5, 5, 5}; C c1(std::begin(t1), std::end(t1)); C c2(std::begin(t2), std::end(t2)); - c1.remove(0); + assert(c1.remove(0) == 1); assert(c1 == c2); } { // LWG issue #526 @@ -83,7 +83,7 @@ int t2[] = { 2, 3, 5, 8, 11}; C c1(std::begin(t1), std::end(t1)); C c2(std::begin(t2), std::end(t2)); - c1.remove(c1.front()); + assert(c1.remove(c1.front()) == 2); assert(c1 == c2); } { @@ -94,7 +94,7 @@ C c; for(int *ip = std::end(t1); ip != std::begin(t1);) c.push_front(S(*--ip)); - c.remove(c.front()); + assert(c.remove(c.front()) == 3); C::const_iterator it = c.begin(); for(int *ip = std::begin(t2); ip != std::end(t2); ++ip, ++it) { assert ( it != c.end()); @@ -110,7 +110,7 @@ const T t2[] = {5, 5, 5}; C c1(std::begin(t1), std::end(t1)); C c2(std::begin(t2), std::end(t2)); - c1.remove(0); + assert(c1.remove(0) == 4); assert(c1 == c2); } { @@ -119,7 +119,7 @@ const T t1[] = {0, 0, 0, 0}; C c1(std::begin(t1), std::end(t1)); C c2; - c1.remove(0); + assert(c1.remove(0) == 4); assert(c1 == c2); } { @@ -129,7 +129,7 @@ const T t2[] = {5, 5, 5}; C c1(std::begin(t1), std::end(t1)); C c2(std::begin(t2), std::end(t2)); - c1.remove(0); + assert(c1.remove(0) == 0); assert(c1 == c2); } { @@ -137,7 +137,7 @@ typedef std::forward_list> C; C c1; C c2; - c1.remove(0); + assert(c1.remove(0) == 0); assert(c1 == c2); } { @@ -147,7 +147,7 @@ const T t2[] = {5, 5, 5}; C c1(std::begin(t1), std::end(t1)); C c2(std::begin(t2), std::end(t2)); - c1.remove(0); + assert(c1.remove(0) == 1); assert(c1 == c2); } #endif Index: test/std/containers/sequences/forwardlist/forwardlist.ops/remove_if.pass.cpp =================================================================== --- test/std/containers/sequences/forwardlist/forwardlist.ops/remove_if.pass.cpp +++ test/std/containers/sequences/forwardlist/forwardlist.ops/remove_if.pass.cpp @@ -35,7 +35,7 @@ C c1(std::begin(t1), std::end(t1)); C c2(std::begin(t2), std::end(t2)); Predicate cp(g); - c1.remove_if(std::ref(cp)); + assert(c1.remove_if(std::ref(cp)) == 4); assert(c1 == c2); assert(cp.count() == static_cast(std::distance(std::begin(t1), std::end(t1)))); } @@ -47,7 +47,7 @@ C c1(std::begin(t1), std::end(t1)); C c2; Predicate cp(g); - c1.remove_if(std::ref(cp)); + assert(c1.remove_if(std::ref(cp)) == 4); assert(c1 == c2); assert(cp.count() == static_cast(std::distance(std::begin(t1), std::end(t1)))); } @@ -60,7 +60,7 @@ C c1(std::begin(t1), std::end(t1)); C c2(std::begin(t2), std::end(t2)); Predicate cp(g); - c1.remove_if(std::ref(cp)); + assert(c1.remove_if(std::ref(cp)) == 0); assert(c1 == c2); assert(cp.count() == static_cast(std::distance(std::begin(t1), std::end(t1)))); } @@ -71,7 +71,7 @@ C c1; C c2; Predicate cp(g); - c1.remove_if(std::ref(cp)); + assert(c1.remove_if(std::ref(cp)) == 0); assert(c1 == c2); assert(cp.count() == 0); } @@ -84,7 +84,7 @@ C c1(std::begin(t1), std::end(t1)); C c2(std::begin(t2), std::end(t2)); Predicate cp(g); - c1.remove_if(std::ref(cp)); + assert(c1.remove_if(std::ref(cp)) == 1); assert(c1 == c2); assert(cp.count() == static_cast(std::distance(std::begin(t1), std::end(t1)))); } @@ -98,7 +98,7 @@ C c1(std::begin(t1), std::end(t1)); C c2(std::begin(t2), std::end(t2)); Predicate cp(g); - c1.remove_if(std::ref(cp)); + assert(c1.remove_if(std::ref(cp)) == 4); assert(c1 == c2); assert(cp.count() == static_cast(std::distance(std::begin(t1), std::end(t1)))); } @@ -110,7 +110,7 @@ C c1(std::begin(t1), std::end(t1)); C c2; Predicate cp(g); - c1.remove_if(std::ref(cp)); + assert(c1.remove_if(std::ref(cp)) == 4); assert(c1 == c2); assert(cp.count() == static_cast(std::distance(std::begin(t1), std::end(t1)))); } @@ -123,7 +123,7 @@ C c1(std::begin(t1), std::end(t1)); C c2(std::begin(t2), std::end(t2)); Predicate cp(g); - c1.remove_if(std::ref(cp)); + assert(c1.remove_if(std::ref(cp)) == 0); assert(c1 == c2); assert(cp.count() == static_cast(std::distance(std::begin(t1), std::end(t1)))); } @@ -134,7 +134,7 @@ C c1; C c2; Predicate cp(g); - c1.remove_if(std::ref(cp)); + assert(c1.remove_if(std::ref(cp)) == 0); assert(c1 == c2); assert(cp.count() == 0); } @@ -147,7 +147,7 @@ C c1(std::begin(t1), std::end(t1)); C c2(std::begin(t2), std::end(t2)); Predicate cp(g); - c1.remove_if(std::ref(cp)); + assert(c1.remove_if(std::ref(cp)) == 1); assert(c1 == c2); assert(cp.count() == static_cast(std::distance(std::begin(t1), std::end(t1)))); } Index: test/std/containers/sequences/forwardlist/forwardlist.ops/unique.pass.cpp =================================================================== --- test/std/containers/sequences/forwardlist/forwardlist.ops/unique.pass.cpp +++ test/std/containers/sequences/forwardlist/forwardlist.ops/unique.pass.cpp @@ -25,7 +25,7 @@ const T t2[] = {0, 5, 0, 5}; C c1(std::begin(t1), std::end(t1)); C c2(std::begin(t2), std::end(t2)); - c1.unique(); + assert(c1.unique() == 3); assert(c1 == c2); } { @@ -35,7 +35,7 @@ const T t2[] = {0}; C c1(std::begin(t1), std::end(t1)); C c2(std::begin(t2), std::end(t2)); - c1.unique(); + assert(c1.unique() == 3); assert(c1 == c2); } { @@ -45,7 +45,7 @@ const T t2[] = {5}; C c1(std::begin(t1), std::end(t1)); C c2(std::begin(t2), std::end(t2)); - c1.unique(); + assert(c1.unique() == 2); assert(c1 == c2); } { @@ -53,7 +53,7 @@ typedef std::forward_list C; C c1; C c2; - c1.unique(); + assert(c1.unique() == 0); assert(c1 == c2); } { @@ -63,7 +63,7 @@ const T t2[] = {5, 0}; C c1(std::begin(t1), std::end(t1)); C c2(std::begin(t2), std::end(t2)); - c1.unique(); + assert(c1.unique() == 2); assert(c1 == c2); } #if TEST_STD_VER >= 11 @@ -74,7 +74,7 @@ const T t2[] = {0, 5, 0, 5}; C c1(std::begin(t1), std::end(t1)); C c2(std::begin(t2), std::end(t2)); - c1.unique(); + assert(c1.unique() == 3); assert(c1 == c2); } { @@ -84,7 +84,7 @@ const T t2[] = {0}; C c1(std::begin(t1), std::end(t1)); C c2(std::begin(t2), std::end(t2)); - c1.unique(); + assert(c1.unique() == 3); assert(c1 == c2); } { @@ -94,7 +94,7 @@ const T t2[] = {5}; C c1(std::begin(t1), std::end(t1)); C c2(std::begin(t2), std::end(t2)); - c1.unique(); + assert(c1.unique() == 2); assert(c1 == c2); } { @@ -102,7 +102,7 @@ typedef std::forward_list> C; C c1; C c2; - c1.unique(); + assert(c1.unique() == 0); assert(c1 == c2); } { @@ -112,7 +112,7 @@ const T t2[] = {5, 0}; C c1(std::begin(t1), std::end(t1)); C c2(std::begin(t2), std::end(t2)); - c1.unique(); + assert(c1.unique() == 2); assert(c1 == c2); } #endif Index: test/std/containers/sequences/list/list.ops/remove.pass.cpp =================================================================== --- test/std/containers/sequences/list/list.ops/remove.pass.cpp +++ test/std/containers/sequences/list/list.ops/remove.pass.cpp @@ -37,7 +37,7 @@ int a1[] = {1, 2, 3, 4}; int a2[] = {1, 2, 4}; std::list c(a1, a1 + 4); - c.remove(3); + assert(c.remove(3) == 1); assert(c == std::list(a2, a2 + 3)); } { // LWG issue #526 @@ -53,7 +53,7 @@ std::list c; for (int *ip = a1; ip < a1 + 8; ++ip) c.push_back(S(*ip)); - c.remove(c.front()); + assert(c.remove(c.front()) == 3); std::list::const_iterator it = c.begin(); for (int *ip = a2; ip < a2 + 5; ++ip, ++it) { assert(it != c.end()); @@ -67,7 +67,7 @@ int a1[] = {1, 2, 3, 4}; int a2[] = {1, 2, 4}; List c(a1, a1 + 4, Alloc::create()); - c.remove(3); + assert(c.remove(3) == 1); assert(c == List(a2, a2 + 3, Alloc::create())); } #if TEST_STD_VER >= 11 @@ -75,7 +75,7 @@ int a1[] = {1, 2, 3, 4}; int a2[] = {1, 2, 4}; std::list> c(a1, a1 + 4); - c.remove(3); + assert(c.remove(3) == 1); assert((c == std::list>(a2, a2 + 3))); } #endif Index: test/std/containers/sequences/list/list.ops/remove_if.pass.cpp =================================================================== --- test/std/containers/sequences/list/list.ops/remove_if.pass.cpp +++ test/std/containers/sequences/list/list.ops/remove_if.pass.cpp @@ -36,7 +36,7 @@ int a2[] = {3, 4}; std::list c(a1, a1+4); Predicate cp(g); - c.remove_if(std::ref(cp)); + assert(c.remove_if(std::ref(cp)) == 2); assert(c == std::list(a2, a2+2)); assert(cp.count() == 4); } @@ -45,7 +45,7 @@ int a2[] = {1, 3}; std::list c(a1, a1+4); Predicate cp(even); - c.remove_if(std::ref(cp)); + assert(c.remove_if(std::ref(cp)) == 2); assert(c == std::list(a2, a2+2)); assert(cp.count() == 4); } @@ -55,7 +55,7 @@ int a2[] = {3, 4}; std::list> c(a1, a1+4); Predicate cp(g); - c.remove_if(std::ref(cp)); + assert(c.remove_if(std::ref(cp)) == 2); assert((c == std::list>(a2, a2+2))); assert(cp.count() == 4); } Index: test/std/containers/sequences/list/list.ops/unique.pass.cpp =================================================================== --- test/std/containers/sequences/list/list.ops/unique.pass.cpp +++ test/std/containers/sequences/list/list.ops/unique.pass.cpp @@ -21,7 +21,7 @@ int a1[] = {2, 1, 1, 4, 4, 4, 4, 3, 3}; int a2[] = {2, 1, 4, 3}; std::list c(a1, a1+sizeof(a1)/sizeof(a1[0])); - c.unique(); + assert(c.unique() == 5); assert(c == std::list(a2, a2+4)); } #if TEST_STD_VER >= 11 @@ -29,7 +29,7 @@ int a1[] = {2, 1, 1, 4, 4, 4, 4, 3, 3}; int a2[] = {2, 1, 4, 3}; std::list> c(a1, a1+sizeof(a1)/sizeof(a1[0])); - c.unique(); + assert(c.unique() == 5); assert((c == std::list>(a2, a2+4))); } #endif