[libc++][ranges] Applied [[nodiscard]] to adjacent_view (#205206)
[[nodiscard]] should be applied to functions where discarding the return value is most likely a correctness issue. - https://libcxx.llvm.org/CodingGuidelines.html - https://wg21.link/range.adjacent Towards https://github.com/llvm/llvm-project/issues/172124 --------- Co-authored-by: A. Jiang <de34@live.cn> Co-authored-by: Hristo Hristov <zingam@outlook.com>
This commit is contained in:
parent
acd0f6fa1e
commit
cf1f0e9d82
2 changed files with 110 additions and 18 deletions
|
|
@ -81,26 +81,26 @@ public:
|
|||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr explicit adjacent_view(_View __base) : __base_(std::move(__base)) {}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr _View base() const&
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _View base() const&
|
||||
requires copy_constructible<_View>
|
||||
{
|
||||
return __base_;
|
||||
}
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr _View base() && { return std::move(__base_); }
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr auto begin()
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _View base() && { return std::move(__base_); }
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto begin()
|
||||
requires(!__simple_view<_View>)
|
||||
{
|
||||
return __iterator<false>(ranges::begin(__base_), ranges::end(__base_));
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr auto begin() const
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto begin() const
|
||||
requires range<const _View> // LWG4482 This is under-constrained.
|
||||
{
|
||||
return __iterator<true>(ranges::begin(__base_), ranges::end(__base_));
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr auto end()
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto end()
|
||||
requires(!__simple_view<_View>)
|
||||
{
|
||||
if constexpr (common_range<_View>) {
|
||||
|
|
@ -110,7 +110,7 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr auto end() const
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto end() const
|
||||
requires range<const _View> // LWG4482 This is under-constrained.
|
||||
{
|
||||
if constexpr (common_range<const _View>) {
|
||||
|
|
@ -120,7 +120,7 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr auto size()
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto size()
|
||||
requires sized_range<_View>
|
||||
{
|
||||
using _ST = decltype(ranges::size(__base_));
|
||||
|
|
@ -130,7 +130,7 @@ public:
|
|||
return static_cast<_ST>(__sz);
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr auto size() const
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto size() const
|
||||
requires sized_range<const _View>
|
||||
{
|
||||
using _ST = decltype(ranges::size(__base_));
|
||||
|
|
@ -205,7 +205,7 @@ public:
|
|||
requires _Const && convertible_to<iterator_t<_View>, iterator_t<const _View>>
|
||||
: __iterator(std::move(__i), make_index_sequence<_Np>{}) {}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr auto operator*() const {
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator*() const {
|
||||
return std::__tuple_transform([](auto& __i) -> decltype(auto) { return *__i; }, __current_);
|
||||
}
|
||||
|
||||
|
|
@ -257,7 +257,7 @@ public:
|
|||
return *this;
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr auto operator[](difference_type __n) const
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator[](difference_type __n) const
|
||||
requires random_access_range<_Base>
|
||||
{
|
||||
return std::__tuple_transform([&](auto& __i) -> decltype(auto) { return __i[__n]; }, __current_);
|
||||
|
|
@ -297,7 +297,7 @@ public:
|
|||
return __x.__current_.back() <=> __y.__current_.back();
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI friend constexpr __iterator operator+(const __iterator& __i, difference_type __n)
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr __iterator operator+(const __iterator& __i, difference_type __n)
|
||||
requires random_access_range<_Base>
|
||||
{
|
||||
auto __r = __i;
|
||||
|
|
@ -305,13 +305,13 @@ public:
|
|||
return __r;
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI friend constexpr __iterator operator+(difference_type __n, const __iterator& __i)
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr __iterator operator+(difference_type __n, const __iterator& __i)
|
||||
requires random_access_range<_Base>
|
||||
{
|
||||
return __i + __n;
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI friend constexpr __iterator operator-(const __iterator& __i, difference_type __n)
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr __iterator operator-(const __iterator& __i, difference_type __n)
|
||||
requires random_access_range<_Base>
|
||||
{
|
||||
auto __r = __i;
|
||||
|
|
@ -319,7 +319,8 @@ public:
|
|||
return __r;
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI friend constexpr difference_type operator-(const __iterator& __x, const __iterator& __y)
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr difference_type
|
||||
operator-(const __iterator& __x, const __iterator& __y)
|
||||
requires sized_sentinel_for<iterator_t<_Base>, iterator_t<_Base>>
|
||||
{
|
||||
return __x.__current_.back() - __y.__current_.back();
|
||||
|
|
@ -366,14 +367,14 @@ public:
|
|||
|
||||
template <bool _OtherConst>
|
||||
requires sized_sentinel_for<sentinel_t<_Base>, iterator_t<__maybe_const<_OtherConst, _View>>>
|
||||
_LIBCPP_HIDE_FROM_ABI friend constexpr range_difference_t<__maybe_const<_OtherConst, _View>>
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr range_difference_t<__maybe_const<_OtherConst, _View>>
|
||||
operator-(const __iterator<_OtherConst>& __x, const __sentinel& __y) {
|
||||
return __x.__current_.back() - __y.__end_;
|
||||
}
|
||||
|
||||
template <bool _OtherConst>
|
||||
requires sized_sentinel_for<sentinel_t<_Base>, iterator_t<__maybe_const<_OtherConst, _View>>>
|
||||
_LIBCPP_HIDE_FROM_ABI friend constexpr range_difference_t<__maybe_const<_OtherConst, _View>>
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr range_difference_t<__maybe_const<_OtherConst, _View>>
|
||||
operator-(const __sentinel& __y, const __iterator<_OtherConst>& __x) {
|
||||
return __y.__end_ - __x.__current_.back();
|
||||
}
|
||||
|
|
@ -389,12 +390,12 @@ template <size_t _Np>
|
|||
struct __fn : __range_adaptor_closure<__fn<_Np>> {
|
||||
template <class _Range>
|
||||
requires(_Np == 0 && forward_range<_Range &&>)
|
||||
_LIBCPP_HIDE_FROM_ABI static constexpr auto operator()(_Range&&) noexcept {
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr auto operator()(_Range&&) noexcept {
|
||||
return empty_view<tuple<>>{};
|
||||
}
|
||||
|
||||
template <class _Ranges>
|
||||
_LIBCPP_HIDE_FROM_ABI static constexpr auto operator()(_Ranges&& __range) noexcept(
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr auto operator()(_Ranges&& __range) noexcept(
|
||||
noexcept(adjacent_view<views::all_t<_Ranges&&>, _Np>(std::forward<_Ranges>(__range))))
|
||||
-> decltype(adjacent_view<views::all_t<_Ranges&&>, _Np>(std::forward<_Ranges>(__range))) {
|
||||
return adjacent_view<views::all_t<_Ranges&&>, _Np>(std::forward<_Ranges>(__range));
|
||||
|
|
|
|||
|
|
@ -0,0 +1,91 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// REQUIRES: std-at-least-c++23
|
||||
|
||||
// Test the libc++ extension that std::ranges::adjacent_view and std::views::adjacent are marked as [[nodiscard]].
|
||||
|
||||
#include <ranges>
|
||||
#include <utility>
|
||||
|
||||
struct View : std::ranges::view_interface<View> {
|
||||
int* begin();
|
||||
const int* begin() const;
|
||||
volatile int* end();
|
||||
const volatile int* end() const;
|
||||
};
|
||||
static_assert(!std::ranges::common_range<View>);
|
||||
static_assert(!std::same_as<std::ranges::iterator_t<View>, std::ranges::iterator_t<const View>>);
|
||||
static_assert(!std::same_as<std::ranges::sentinel_t<View>, std::ranges::sentinel_t<const View>>);
|
||||
|
||||
void test() {
|
||||
int range[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
|
||||
auto v = View{} | std::views::adjacent<2>;
|
||||
|
||||
// [range.adjacent.view]
|
||||
|
||||
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
std::as_const(v).base();
|
||||
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
std::move(v).base();
|
||||
|
||||
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
v.begin();
|
||||
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
std::as_const(v).begin();
|
||||
|
||||
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
v.end();
|
||||
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
std::as_const(v).end();
|
||||
|
||||
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
v.size();
|
||||
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
std::as_const(v).size();
|
||||
|
||||
// [range.adjacent.iterator]
|
||||
|
||||
auto it = v.begin();
|
||||
auto c_it = std::as_const(v).begin();
|
||||
|
||||
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
*c_it;
|
||||
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
c_it[0];
|
||||
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
it + 0;
|
||||
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
0 + it;
|
||||
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
it - 0;
|
||||
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
it - it;
|
||||
|
||||
// [range.adjacent.sentinel]
|
||||
|
||||
auto st = v.end();
|
||||
|
||||
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
it - st;
|
||||
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
st - it;
|
||||
|
||||
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
st - c_it;
|
||||
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
c_it - st;
|
||||
|
||||
// [range.adjacent.overview]
|
||||
|
||||
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
std::views::adjacent<0>(range);
|
||||
|
||||
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
std::views::adjacent<2>(range);
|
||||
}
|
||||
Loading…
Reference in a new issue