diff options
| author | Nico Weber <nicolasweber@gmx.de> | 2019-04-03 18:13:08 +0000 |
|---|---|---|
| committer | Nico Weber <nicolasweber@gmx.de> | 2019-04-03 18:13:08 +0000 |
| commit | 1362d7ef885d1e8136e19d85c0eeba3477b53020 (patch) | |
| tree | 20c29ea5d2e11b313daaff58043d72fa301dcf9a /libcxx/test | |
| parent | 956168c8029b4cc8c1d317f0326a7c1238101cb7 (diff) | |
| download | bcm5719-llvm-1362d7ef885d1e8136e19d85c0eeba3477b53020.tar.gz bcm5719-llvm-1362d7ef885d1e8136e19d85c0eeba3477b53020.zip | |
libcxx: Add _LIBCPP_NODISCARD_EXT to 38 more functions
This builds on the work done in r342808 and adds _LIBCPP_NODISCARD_EXT
to 37 more functions, namely:
adjacent_find, all_of, any_of, binary_search, clamp, count_if, count,
equal_range, equal, find_end, find_first_not_of, find_first_of, find_if,
find, includes, is_heap_until, is_heap, is_partitioned, is_permutation,
is_sorted_until, is_sorted, lexicographical_compare, lower_bound,
max_element, max, min_element, min, minmax_element, minmax, mismatch,
none_of, remove_if, remove, search_n, search, unique, upper_bound
The motivation here is that we noticed that find_if is nodiscard with
Visual Studio's standard library, and we deemed that useful
(https://crbug.com/948122).
https://devblogs.microsoft.com/cppblog/c17-progress-in-vs-2017-15-5-and-15-6/
says "Our criteria for emitting the warning are: discarding the return
value is a guaranteed leak [...], discarding the return value is
near-guaranteed to be incorrect (e.g. remove()/remove_if()/unique()), or
the function is essentially a pure observer (e.g. vector::empty() and
std::is_sorted())." so I went through algorithm and tried to apply these
criteria.
Some of these, like vector::empty() are already nodiscard per C++
standard and didn't need changing.
I didn't (yet?) go over std::string::find* methods which should probably
have _LIBCPP_NODISCARD_EXT too (but not as part of this change).
Differential Revision: https://reviews.llvm.org/D60145
llvm-svn: 357619
Diffstat (limited to 'libcxx/test')
| -rw-r--r-- | libcxx/test/libcxx/diagnostics/nodiscard_extensions.fail.cpp | 258 | ||||
| -rw-r--r-- | libcxx/test/libcxx/diagnostics/nodiscard_extensions.pass.cpp | 104 |
2 files changed, 355 insertions, 7 deletions
diff --git a/libcxx/test/libcxx/diagnostics/nodiscard_extensions.fail.cpp b/libcxx/test/libcxx/diagnostics/nodiscard_extensions.fail.cpp index a265e8755b5..91a63f09e9f 100644 --- a/libcxx/test/libcxx/diagnostics/nodiscard_extensions.fail.cpp +++ b/libcxx/test/libcxx/diagnostics/nodiscard_extensions.fail.cpp @@ -22,15 +22,265 @@ // MODULES_DEFINES: _LIBCPP_ENABLE_NODISCARD #define _LIBCPP_ENABLE_NODISCARD +#include <algorithm> +#include <functional> +#include <iterator> #include <memory> #include "test_macros.h" +struct P { + bool operator()(int) const { return false; } +}; + int main(int, char**) { - { - // expected-error-re@+1 {{ignoring return value of function declared with {{'nodiscard'|warn_unused_result}} attribute}} - std::get_temporary_buffer<int>(1); - } + int arr[1] = { 1 }; + + // expected-error-re@+1 {{ignoring return value of function declared with {{'nodiscard'|warn_unused_result}} attribute}} + std::adjacent_find(std::begin(arr), std::end(arr)); + + // expected-error-re@+1 {{ignoring return value of function declared with {{'nodiscard'|warn_unused_result}} attribute}} + std::adjacent_find(std::begin(arr), std::end(arr), std::greater<int>()); + + // expected-error-re@+1 {{ignoring return value of function declared with {{'nodiscard'|warn_unused_result}} attribute}} + std::all_of(std::begin(arr), std::end(arr), P()); + + // expected-error-re@+1 {{ignoring return value of function declared with {{'nodiscard'|warn_unused_result}} attribute}} + std::any_of(std::begin(arr), std::end(arr), P()); + + // expected-error-re@+1 {{ignoring return value of function declared with {{'nodiscard'|warn_unused_result}} attribute}} + std::binary_search(std::begin(arr), std::end(arr), 1); + + // expected-error-re@+1 {{ignoring return value of function declared with {{'nodiscard'|warn_unused_result}} attribute}} + std::binary_search(std::begin(arr), std::end(arr), 1, std::greater<int>()); + + // expected-error-re@+1 {{ignoring return value of function declared with {{'nodiscard'|warn_unused_result}} attribute}} + std::clamp(2, 1, 3); + + // expected-error-re@+1 {{ignoring return value of function declared with {{'nodiscard'|warn_unused_result}} attribute}} + std::clamp(2, 1, 3, std::greater<int>()); + + // expected-error-re@+1 {{ignoring return value of function declared with {{'nodiscard'|warn_unused_result}} attribute}} + std::count_if(std::begin(arr), std::end(arr), P()); + + // expected-error-re@+1 {{ignoring return value of function declared with {{'nodiscard'|warn_unused_result}} attribute}} + std::count(std::begin(arr), std::end(arr), 1); + + // expected-error-re@+1 {{ignoring return value of function declared with {{'nodiscard'|warn_unused_result}} attribute}} + std::equal_range(std::begin(arr), std::end(arr), 1); + + // expected-error-re@+1 {{ignoring return value of function declared with {{'nodiscard'|warn_unused_result}} attribute}} + std::equal_range(std::begin(arr), std::end(arr), 1, std::greater<int>()); + + // expected-error-re@+1 {{ignoring return value of function declared with {{'nodiscard'|warn_unused_result}} attribute}} + std::equal(std::begin(arr), std::end(arr), std::begin(arr)); + + // expected-error-re@+1 {{ignoring return value of function declared with {{'nodiscard'|warn_unused_result}} attribute}} + std::equal(std::begin(arr), std::end(arr), std::begin(arr), + std::greater<int>()); + + // expected-error-re@+1 {{ignoring return value of function declared with {{'nodiscard'|warn_unused_result}} attribute}} + std::equal(std::begin(arr), std::end(arr), std::begin(arr), std::end(arr)); + + // expected-error-re@+1 {{ignoring return value of function declared with {{'nodiscard'|warn_unused_result}} attribute}} + std::equal(std::begin(arr), std::end(arr), std::begin(arr), std::end(arr), + std::greater<int>()); + + // expected-error-re@+1 {{ignoring return value of function declared with {{'nodiscard'|warn_unused_result}} attribute}} + std::find_end(std::begin(arr), std::end(arr), std::begin(arr), std::end(arr)); + + // expected-error-re@+1 {{ignoring return value of function declared with {{'nodiscard'|warn_unused_result}} attribute}} + std::find_end(std::begin(arr), std::end(arr), std::begin(arr), std::end(arr), + std::greater<int>()); + + // expected-error-re@+1 {{ignoring return value of function declared with {{'nodiscard'|warn_unused_result}} attribute}} + std::find_first_of(std::begin(arr), std::end(arr), std::begin(arr), + std::end(arr)); + + // expected-error-re@+1 {{ignoring return value of function declared with {{'nodiscard'|warn_unused_result}} attribute}} + std::find_first_of(std::begin(arr), std::end(arr), std::begin(arr), + std::end(arr), std::greater<int>()); + + // expected-error-re@+1 {{ignoring return value of function declared with {{'nodiscard'|warn_unused_result}} attribute}} + std::find_if_not(std::begin(arr), std::end(arr), P()); + + // expected-error-re@+1 {{ignoring return value of function declared with {{'nodiscard'|warn_unused_result}} attribute}} + std::find_if(std::begin(arr), std::end(arr), P()); + + // expected-error-re@+1 {{ignoring return value of function declared with {{'nodiscard'|warn_unused_result}} attribute}} + std::find(std::begin(arr), std::end(arr), 1); + + // expected-error-re@+1 {{ignoring return value of function declared with {{'nodiscard'|warn_unused_result}} attribute}} + std::get_temporary_buffer<int>(1); + + // expected-error-re@+1 {{ignoring return value of function declared with {{'nodiscard'|warn_unused_result}} attribute}} + std::includes(std::begin(arr), std::end(arr), std::begin(arr), std::end(arr)); + + // expected-error-re@+1 {{ignoring return value of function declared with {{'nodiscard'|warn_unused_result}} attribute}} + std::includes(std::begin(arr), std::end(arr), std::begin(arr), std::end(arr), + std::greater<int>()); + + // expected-error-re@+1 {{ignoring return value of function declared with {{'nodiscard'|warn_unused_result}} attribute}} + std::is_heap_until(std::begin(arr), std::end(arr)); + + // expected-error-re@+1 {{ignoring return value of function declared with {{'nodiscard'|warn_unused_result}} attribute}} + std::is_heap_until(std::begin(arr), std::end(arr), std::greater<int>()); + + // expected-error-re@+1 {{ignoring return value of function declared with {{'nodiscard'|warn_unused_result}} attribute}} + std::is_heap(std::begin(arr), std::end(arr)); + + // expected-error-re@+1 {{ignoring return value of function declared with {{'nodiscard'|warn_unused_result}} attribute}} + std::is_heap(std::begin(arr), std::end(arr), std::greater<int>()); + + // expected-error-re@+1 {{ignoring return value of function declared with {{'nodiscard'|warn_unused_result}} attribute}} + std::is_partitioned(std::begin(arr), std::end(arr), P()); + + // expected-error-re@+1 {{ignoring return value of function declared with {{'nodiscard'|warn_unused_result}} attribute}} + std::is_permutation(std::begin(arr), std::end(arr), std::begin(arr)); + + // expected-error-re@+1 {{ignoring return value of function declared with {{'nodiscard'|warn_unused_result}} attribute}} + std::is_permutation(std::begin(arr), std::end(arr), std::begin(arr), + std::greater<int>()); + + // expected-error-re@+1 {{ignoring return value of function declared with {{'nodiscard'|warn_unused_result}} attribute}} + std::is_permutation(std::begin(arr), std::end(arr), std::begin(arr), + std::end(arr)); + + // expected-error-re@+1 {{ignoring return value of function declared with {{'nodiscard'|warn_unused_result}} attribute}} + std::is_permutation(std::begin(arr), std::end(arr), std::begin(arr), + std::end(arr), std::greater<int>()); + + // expected-error-re@+1 {{ignoring return value of function declared with {{'nodiscard'|warn_unused_result}} attribute}} + std::is_sorted_until(std::begin(arr), std::end(arr)); + + // expected-error-re@+1 {{ignoring return value of function declared with {{'nodiscard'|warn_unused_result}} attribute}} + std::is_sorted_until(std::begin(arr), std::end(arr), std::greater<int>()); + + // expected-error-re@+1 {{ignoring return value of function declared with {{'nodiscard'|warn_unused_result}} attribute}} + std::is_sorted(std::begin(arr), std::end(arr)); + + // expected-error-re@+1 {{ignoring return value of function declared with {{'nodiscard'|warn_unused_result}} attribute}} + std::is_sorted(std::begin(arr), std::end(arr), std::greater<int>()); + + // expected-error-re@+1 {{ignoring return value of function declared with {{'nodiscard'|warn_unused_result}} attribute}} + std::lexicographical_compare(std::begin(arr), std::end(arr), std::begin(arr), + std::end(arr)); + + // expected-error-re@+1 {{ignoring return value of function declared with {{'nodiscard'|warn_unused_result}} attribute}} + std::lexicographical_compare(std::begin(arr), std::end(arr), std::begin(arr), + std::end(arr), std::greater<int>()); + + // expected-error-re@+1 {{ignoring return value of function declared with {{'nodiscard'|warn_unused_result}} attribute}} + std::lower_bound(std::begin(arr), std::end(arr), 1); + + // expected-error-re@+1 {{ignoring return value of function declared with {{'nodiscard'|warn_unused_result}} attribute}} + std::lower_bound(std::begin(arr), std::end(arr), 1, std::greater<int>()); + + // expected-error-re@+1 {{ignoring return value of function declared with {{'nodiscard'|warn_unused_result}} attribute}} + std::max_element(std::begin(arr), std::end(arr)); + + // expected-error-re@+1 {{ignoring return value of function declared with {{'nodiscard'|warn_unused_result}} attribute}} + std::max_element(std::begin(arr), std::end(arr), std::greater<int>()); + + // expected-error-re@+1 {{ignoring return value of function declared with {{'nodiscard'|warn_unused_result}} attribute}} + std::max(1, 2); + + // expected-error-re@+1 {{ignoring return value of function declared with {{'nodiscard'|warn_unused_result}} attribute}} + std::max(1, 2, std::greater<int>()); + + // expected-error-re@+1 {{ignoring return value of function declared with {{'nodiscard'|warn_unused_result}} attribute}} + std::max({1, 2, 3}); + + // expected-error-re@+1 {{ignoring return value of function declared with {{'nodiscard'|warn_unused_result}} attribute}} + std::max({1, 2, 3}, std::greater<int>()); + + // expected-error-re@+1 {{ignoring return value of function declared with {{'nodiscard'|warn_unused_result}} attribute}} + std::min_element(std::begin(arr), std::end(arr)); + + // expected-error-re@+1 {{ignoring return value of function declared with {{'nodiscard'|warn_unused_result}} attribute}} + std::min_element(std::begin(arr), std::end(arr), std::greater<int>()); + + // expected-error-re@+1 {{ignoring return value of function declared with {{'nodiscard'|warn_unused_result}} attribute}} + std::min(1, 2); + + // expected-error-re@+1 {{ignoring return value of function declared with {{'nodiscard'|warn_unused_result}} attribute}} + std::min(1, 2, std::greater<int>()); + + // expected-error-re@+1 {{ignoring return value of function declared with {{'nodiscard'|warn_unused_result}} attribute}} + std::min({1, 2, 3}); + + // expected-error-re@+1 {{ignoring return value of function declared with {{'nodiscard'|warn_unused_result}} attribute}} + std::min({1, 2, 3}, std::greater<int>()); + + // expected-error-re@+1 {{ignoring return value of function declared with {{'nodiscard'|warn_unused_result}} attribute}} + std::minmax_element(std::begin(arr), std::end(arr)); + + // expected-error-re@+1 {{ignoring return value of function declared with {{'nodiscard'|warn_unused_result}} attribute}} + std::minmax_element(std::begin(arr), std::end(arr), std::greater<int>()); + + // expected-error-re@+1 {{ignoring return value of function declared with {{'nodiscard'|warn_unused_result}} attribute}} + std::minmax(1, 2); + + // expected-error-re@+1 {{ignoring return value of function declared with {{'nodiscard'|warn_unused_result}} attribute}} + std::minmax(1, 2, std::greater<int>()); + + // expected-error-re@+1 {{ignoring return value of function declared with {{'nodiscard'|warn_unused_result}} attribute}} + std::minmax({1, 2, 3}); + + // expected-error-re@+1 {{ignoring return value of function declared with {{'nodiscard'|warn_unused_result}} attribute}} + std::minmax({1, 2, 3}, std::greater<int>()); + + // expected-error-re@+1 {{ignoring return value of function declared with {{'nodiscard'|warn_unused_result}} attribute}} + std::mismatch(std::begin(arr), std::end(arr), std::begin(arr)); + + // expected-error-re@+1 {{ignoring return value of function declared with {{'nodiscard'|warn_unused_result}} attribute}} + std::mismatch(std::begin(arr), std::end(arr), std::begin(arr), + std::greater<int>()); + + // expected-error-re@+1 {{ignoring return value of function declared with {{'nodiscard'|warn_unused_result}} attribute}} + std::mismatch(std::begin(arr), std::end(arr), std::begin(arr), std::end(arr)); + + // expected-error-re@+1 {{ignoring return value of function declared with {{'nodiscard'|warn_unused_result}} attribute}} + std::mismatch(std::begin(arr), std::end(arr), std::begin(arr), std::end(arr), + std::greater<int>()); + + // expected-error-re@+1 {{ignoring return value of function declared with {{'nodiscard'|warn_unused_result}} attribute}} + std::none_of(std::begin(arr), std::end(arr), P()); + + // expected-error-re@+1 {{ignoring return value of function declared with {{'nodiscard'|warn_unused_result}} attribute}} + std::remove_if(std::begin(arr), std::end(arr), P()); + + // expected-error-re@+1 {{ignoring return value of function declared with {{'nodiscard'|warn_unused_result}} attribute}} + std::remove(std::begin(arr), std::end(arr), 1); + + // expected-error-re@+1 {{ignoring return value of function declared with {{'nodiscard'|warn_unused_result}} attribute}} + std::search_n(std::begin(arr), std::end(arr), 1, 1); + + // expected-error-re@+1 {{ignoring return value of function declared with {{'nodiscard'|warn_unused_result}} attribute}} + std::search_n(std::begin(arr), std::end(arr), 1, 1, std::greater<int>()); + + // expected-error-re@+1 {{ignoring return value of function declared with {{'nodiscard'|warn_unused_result}} attribute}} + std::search(std::begin(arr), std::end(arr), std::begin(arr), std::end(arr)); + + // expected-error-re@+1 {{ignoring return value of function declared with {{'nodiscard'|warn_unused_result}} attribute}} + std::search(std::begin(arr), std::end(arr), std::begin(arr), std::end(arr), + std::greater<int>()); + + // expected-error-re@+1 {{ignoring return value of function declared with {{'nodiscard'|warn_unused_result}} attribute}} + std::search(std::begin(arr), std::end(arr), + std::default_searcher(std::begin(arr), std::end(arr))); + + // expected-error-re@+1 {{ignoring return value of function declared with {{'nodiscard'|warn_unused_result}} attribute}} + std::unique(std::begin(arr), std::end(arr)); + + // expected-error-re@+1 {{ignoring return value of function declared with {{'nodiscard'|warn_unused_result}} attribute}} + std::unique(std::begin(arr), std::end(arr), std::greater<int>()); + + // expected-error-re@+1 {{ignoring return value of function declared with {{'nodiscard'|warn_unused_result}} attribute}} + std::upper_bound(std::begin(arr), std::end(arr), 1); + + // expected-error-re@+1 {{ignoring return value of function declared with {{'nodiscard'|warn_unused_result}} attribute}} + std::upper_bound(std::begin(arr), std::end(arr), 1, std::greater<int>()); return 0; } diff --git a/libcxx/test/libcxx/diagnostics/nodiscard_extensions.pass.cpp b/libcxx/test/libcxx/diagnostics/nodiscard_extensions.pass.cpp index 87615fbd0f5..efc2bc82dcc 100644 --- a/libcxx/test/libcxx/diagnostics/nodiscard_extensions.pass.cpp +++ b/libcxx/test/libcxx/diagnostics/nodiscard_extensions.pass.cpp @@ -17,14 +17,112 @@ // be tested here and in nodiscard_extensions.fail.cpp. They should also // be listed in `UsingLibcxx.rst` in the documentation for the extension. +#include <algorithm> +#include <functional> +#include <iterator> #include <memory> #include "test_macros.h" +struct P { + bool operator()(int) const { return false; } +}; + int main(int, char**) { - { - std::get_temporary_buffer<int>(1); // intentional memory leak. - } + int arr[1] = { 1 }; + + std::adjacent_find(std::begin(arr), std::end(arr)); + std::adjacent_find(std::begin(arr), std::end(arr), std::greater<int>()); + std::all_of(std::begin(arr), std::end(arr), P()); + std::any_of(std::begin(arr), std::end(arr), P()); + std::binary_search(std::begin(arr), std::end(arr), 1); + std::binary_search(std::begin(arr), std::end(arr), 1, std::greater<int>()); + std::clamp(2, 1, 3); + std::clamp(2, 1, 3, std::greater<int>()); + std::count_if(std::begin(arr), std::end(arr), P()); + std::count(std::begin(arr), std::end(arr), 1); + std::equal_range(std::begin(arr), std::end(arr), 1); + std::equal_range(std::begin(arr), std::end(arr), 1, std::greater<int>()); + std::equal(std::begin(arr), std::end(arr), std::begin(arr)); + std::equal(std::begin(arr), std::end(arr), std::begin(arr), + std::greater<int>()); + std::equal(std::begin(arr), std::end(arr), std::begin(arr), std::end(arr)); + std::equal(std::begin(arr), std::end(arr), std::begin(arr), std::end(arr), + std::greater<int>()); + std::find_end(std::begin(arr), std::end(arr), std::begin(arr), std::end(arr)); + std::find_end(std::begin(arr), std::end(arr), std::begin(arr), std::end(arr), + std::greater<int>()); + std::find_first_of(std::begin(arr), std::end(arr), std::begin(arr), + std::end(arr)); + std::find_first_of(std::begin(arr), std::end(arr), std::begin(arr), + std::end(arr), std::greater<int>()); + std::find_if_not(std::begin(arr), std::end(arr), P()); + std::find_if(std::begin(arr), std::end(arr), P()); + std::find(std::begin(arr), std::end(arr), 1); + std::get_temporary_buffer<int>(1); // intentional memory leak. + std::includes(std::begin(arr), std::end(arr), std::begin(arr), std::end(arr)); + std::includes(std::begin(arr), std::end(arr), std::begin(arr), std::end(arr), + std::greater<int>()); + std::is_heap_until(std::begin(arr), std::end(arr)); + std::is_heap_until(std::begin(arr), std::end(arr), std::greater<int>()); + std::is_heap(std::begin(arr), std::end(arr)); + std::is_heap(std::begin(arr), std::end(arr), std::greater<int>()); + std::is_partitioned(std::begin(arr), std::end(arr), P()); + std::is_permutation(std::begin(arr), std::end(arr), std::begin(arr)); + std::is_permutation(std::begin(arr), std::end(arr), std::begin(arr), + std::greater<int>()); + std::is_permutation(std::begin(arr), std::end(arr), std::begin(arr), + std::end(arr)); + std::is_permutation(std::begin(arr), std::end(arr), std::begin(arr), + std::end(arr), std::greater<int>()); + std::is_sorted_until(std::begin(arr), std::end(arr)); + std::is_sorted_until(std::begin(arr), std::end(arr), std::greater<int>()); + std::is_sorted(std::begin(arr), std::end(arr)); + std::is_sorted(std::begin(arr), std::end(arr), std::greater<int>()); + std::lexicographical_compare(std::begin(arr), std::end(arr), std::begin(arr), + std::end(arr)); + std::lexicographical_compare(std::begin(arr), std::end(arr), std::begin(arr), + std::end(arr), std::greater<int>()); + std::lower_bound(std::begin(arr), std::end(arr), 1); + std::lower_bound(std::begin(arr), std::end(arr), 1, std::greater<int>()); + std::max_element(std::begin(arr), std::end(arr)); + std::max_element(std::begin(arr), std::end(arr), std::greater<int>()); + std::max(1, 2); + std::max(1, 2, std::greater<int>()); + std::max({1, 2, 3}); + std::max({1, 2, 3}, std::greater<int>()); + std::min_element(std::begin(arr), std::end(arr)); + std::min_element(std::begin(arr), std::end(arr), std::greater<int>()); + std::min(1, 2); + std::min(1, 2, std::greater<int>()); + std::min({1, 2, 3}); + std::min({1, 2, 3}, std::greater<int>()); + std::minmax_element(std::begin(arr), std::end(arr)); + std::minmax_element(std::begin(arr), std::end(arr), std::greater<int>()); + std::minmax(1, 2); + std::minmax(1, 2, std::greater<int>()); + std::minmax({1, 2, 3}); + std::minmax({1, 2, 3}, std::greater<int>()); + std::mismatch(std::begin(arr), std::end(arr), std::begin(arr)); + std::mismatch(std::begin(arr), std::end(arr), std::begin(arr), + std::greater<int>()); + std::mismatch(std::begin(arr), std::end(arr), std::begin(arr), std::end(arr)); + std::mismatch(std::begin(arr), std::end(arr), std::begin(arr), std::end(arr), + std::greater<int>()); + std::none_of(std::begin(arr), std::end(arr), P()); + std::remove_if(std::begin(arr), std::end(arr), P()); + std::remove(std::begin(arr), std::end(arr), 1); + std::search_n(std::begin(arr), std::end(arr), 1, 1); + std::search_n(std::begin(arr), std::end(arr), 1, 1, std::greater<int>()); + std::search(std::begin(arr), std::end(arr), std::begin(arr), std::end(arr)); + std::search(std::begin(arr), std::end(arr), std::begin(arr), std::end(arr), + std::greater<int>()); + std::search(std::begin(arr), std::end(arr), + std::default_searcher(std::begin(arr), std::end(arr))); + std::unique(std::begin(arr), std::end(arr)); + std::unique(std::begin(arr), std::end(arr), std::greater<int>()); + std::upper_bound(std::begin(arr), std::end(arr), 1); + std::upper_bound(std::begin(arr), std::end(arr), 1, std::greater<int>()); return 0; } |

