From 89599e8b201a85c4555e72580b7137e4cce71c94 Mon Sep 17 00:00:00 2001 From: zoecarver Date: Tue, 1 Jun 2021 14:54:29 -0700 Subject: [PATCH] [libcxx][ranges] Add concepts in range.utility.helpers. There are no changes to public APIs. Differential Revision: https://reviews.llvm.org/D103493 --- libcxx/include/__iterator/concepts.h | 4 + libcxx/include/__iterator/iterator_traits.h | 8 +- libcxx/include/__ranges/view.h | 5 ++ libcxx/include/concepts | 3 + .../different_from.compile.pass.cpp | 30 +++++++ .../has_arrow.compile.pass.cpp | 84 +++++++++++++++++++ .../simple_view.compile.pass.cpp | 49 +++++++++++ 7 files changed, 176 insertions(+), 7 deletions(-) create mode 100644 libcxx/test/libcxx/ranges/range.utility.helpers/different_from.compile.pass.cpp create mode 100644 libcxx/test/libcxx/ranges/range.utility.helpers/has_arrow.compile.pass.cpp create mode 100644 libcxx/test/libcxx/ranges/range.utility.helpers/simple_view.compile.pass.cpp diff --git a/libcxx/include/__iterator/concepts.h b/libcxx/include/__iterator/concepts.h index 654d27bf250b..8b83eb1e90c0 100644 --- a/libcxx/include/__iterator/concepts.h +++ b/libcxx/include/__iterator/concepts.h @@ -168,6 +168,10 @@ concept contiguous_iterator = { _VSTD::to_address(__i) } -> same_as>>; }; + +template +concept __has_arrow = input_iterator<_Ip> && (is_pointer_v<_Ip> || requires(_Ip __i) { __i.operator->(); }); + // clang-format on #endif // !defined(_LIBCPP_HAS_NO_RANGES) diff --git a/libcxx/include/__iterator/iterator_traits.h b/libcxx/include/__iterator/iterator_traits.h index 307ee143c1d2..06b199b85979 100644 --- a/libcxx/include/__iterator/iterator_traits.h +++ b/libcxx/include/__iterator/iterator_traits.h @@ -255,13 +255,7 @@ struct __iterator_traits_member_pointer_or_arrow_or_void<_Ip> { using type = typ // Otherwise, if `decltype(declval().operator->())` is well-formed, then `pointer` names that // type. template -concept __has_arrow = - requires(_Ip& __i) { - __i.operator->(); - }; - -template - requires __has_arrow<_Ip> && (!__has_member_pointer<_Ip>) + requires requires(_Ip& __i) { __i.operator->(); } && (!__has_member_pointer<_Ip>) struct __iterator_traits_member_pointer_or_arrow_or_void<_Ip> { using type = decltype(declval<_Ip&>().operator->()); }; diff --git a/libcxx/include/__ranges/view.h b/libcxx/include/__ranges/view.h index 11c0ae2db072..55f8928f3c59 100644 --- a/libcxx/include/__ranges/view.h +++ b/libcxx/include/__ranges/view.h @@ -40,6 +40,11 @@ concept view = default_initializable<_Tp> && enable_view<_Tp>; +template +concept __simple_view = + view<_Range> && range && + same_as, iterator_t> && + same_as, iterator_t>; } // end namespace ranges #endif // !_LIBCPP_HAS_NO_RANGES diff --git a/libcxx/include/concepts b/libcxx/include/concepts index 6c8f325af8af..0b51f53dcc39 100644 --- a/libcxx/include/concepts +++ b/libcxx/include/concepts @@ -442,6 +442,9 @@ concept equivalence_relation = relation<_Rp, _Tp, _Up>; template concept strict_weak_order = relation<_Rp, _Tp, _Up>; +template +concept __different_from = !same_as, remove_cvref_t<_Up>>; + #endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_CONCEPTS) _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/test/libcxx/ranges/range.utility.helpers/different_from.compile.pass.cpp b/libcxx/test/libcxx/ranges/range.utility.helpers/different_from.compile.pass.cpp new file mode 100644 index 000000000000..ecea0eeb3890 --- /dev/null +++ b/libcxx/test/libcxx/ranges/range.utility.helpers/different_from.compile.pass.cpp @@ -0,0 +1,30 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: libcpp-no-concepts +// UNSUPPORTED: gcc-10 + +#include + +#include "test_macros.h" + +static_assert(std::__different_from); +static_assert(std::__different_from); +static_assert(!std::__different_from); +static_assert(!std::__different_from); +static_assert(!std::__different_from); +static_assert(!std::__different_from); +static_assert(!std::__different_from); +static_assert(!std::__different_from); +static_assert(!std::__different_from); +static_assert(!std::__different_from); +static_assert(std::__different_from); + diff --git a/libcxx/test/libcxx/ranges/range.utility.helpers/has_arrow.compile.pass.cpp b/libcxx/test/libcxx/ranges/range.utility.helpers/has_arrow.compile.pass.cpp new file mode 100644 index 000000000000..889cf8b215e0 --- /dev/null +++ b/libcxx/test/libcxx/ranges/range.utility.helpers/has_arrow.compile.pass.cpp @@ -0,0 +1,84 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: libcpp-no-concepts +// UNSUPPORTED: gcc-10 + +#include + +#include "test_macros.h" + +struct simple_iter { + typedef std::input_iterator_tag iterator_category; + typedef int value_type; + typedef std::ptrdiff_t difference_type; + typedef int* pointer; + typedef int& reference; + + reference operator*() const; + pointer operator->() const; + friend bool operator==(const simple_iter&, const simple_iter&); + friend bool operator< (const simple_iter&, const simple_iter&); + friend bool operator<=(const simple_iter&, const simple_iter&); + friend bool operator> (const simple_iter&, const simple_iter&); + friend bool operator>=(const simple_iter&, const simple_iter&); + + simple_iter& operator++(); + simple_iter operator++(int); +}; + +struct no_star { + typedef std::input_iterator_tag iterator_category; + typedef int value_type; + typedef std::ptrdiff_t difference_type; + typedef int* pointer; + typedef int& reference; + + /* reference operator*() const; */ + pointer operator->() const; + friend bool operator==(const simple_iter&, const simple_iter&); + friend bool operator< (const simple_iter&, const simple_iter&); + friend bool operator<=(const simple_iter&, const simple_iter&); + friend bool operator> (const simple_iter&, const simple_iter&); + friend bool operator>=(const simple_iter&, const simple_iter&); + + simple_iter& operator++(); + simple_iter operator++(int); +}; + +struct no_arrow { + typedef std::input_iterator_tag iterator_category; + typedef int value_type; + typedef std::ptrdiff_t difference_type; + typedef int* pointer; + typedef int& reference; + + reference operator*() const; + /* pointer operator->() const; */ + friend bool operator==(const simple_iter&, const simple_iter&); + friend bool operator< (const simple_iter&, const simple_iter&); + friend bool operator<=(const simple_iter&, const simple_iter&); + friend bool operator> (const simple_iter&, const simple_iter&); + friend bool operator>=(const simple_iter&, const simple_iter&); + + simple_iter& operator++(); + simple_iter operator++(int); +}; + +struct E {}; +struct Incomplete; + +static_assert(std::__has_arrow); +static_assert(std::__has_arrow); +static_assert(!std::__has_arrow); // Because it's not an input_iterator. +static_assert(std::__has_arrow); +static_assert(!std::__has_arrow); +static_assert(!std::__has_arrow); diff --git a/libcxx/test/libcxx/ranges/range.utility.helpers/simple_view.compile.pass.cpp b/libcxx/test/libcxx/ranges/range.utility.helpers/simple_view.compile.pass.cpp new file mode 100644 index 000000000000..c544d922c181 --- /dev/null +++ b/libcxx/test/libcxx/ranges/range.utility.helpers/simple_view.compile.pass.cpp @@ -0,0 +1,49 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: libcpp-no-concepts +// UNSUPPORTED: gcc-10 + +#include + +#include "test_macros.h" +#include "test_iterators.h" + +struct SimpleView : std::ranges::view_base { + friend int* begin(SimpleView&); + friend int* begin(SimpleView const&); + friend int* end(SimpleView&); + friend int* end(SimpleView const&); +}; + +struct WrongConstView : std::ranges::view_base { + friend int* begin(WrongConstView&); + friend const int* begin(WrongConstView const&); + friend int* end(WrongConstView&); + friend const int* end(WrongConstView const&); +}; + +struct NoConstView : std::ranges::view_base { + friend int* begin(NoConstView&); + friend int* end(NoConstView&); +}; + +struct DifferentSentinel : std::ranges::view_base { + friend int* begin(DifferentSentinel&); + friend int* begin(DifferentSentinel const&); + friend sentinel_wrapper end(DifferentSentinel&); + friend sentinel_wrapper end(DifferentSentinel const&); +}; + +static_assert( std::ranges::__simple_view); +static_assert(!std::ranges::__simple_view); +static_assert(!std::ranges::__simple_view); +static_assert(!std::ranges::__simple_view); -- 2.34.1