[libcxx-commits] [libcxx] 483f7f5 - [libc++] [ranges] Implement ranges::cdata.
Arthur O'Dwyer via libcxx-commits
libcxx-commits at lists.llvm.org
Wed Jan 12 19:07:26 PST 2022
Author: Arthur O'Dwyer
Date: 2022-01-12T22:07:13-05:00
New Revision: 483f7f55365209dc39df9fa31b2cce0f03e9b4ec
URL: https://github.com/llvm/llvm-project/commit/483f7f55365209dc39df9fa31b2cce0f03e9b4ec
DIFF: https://github.com/llvm/llvm-project/commit/483f7f55365209dc39df9fa31b2cce0f03e9b4ec.diff
LOG: [libc++] [ranges] Implement ranges::cdata.
Differential Revision: https://reviews.llvm.org/D117044
Added:
Modified:
libcxx/docs/Status/RangesPaper.csv
libcxx/include/__ranges/data.h
libcxx/test/std/library/description/conventions/customization.point.object/cpo.compile.pass.cpp
libcxx/test/std/ranges/range.access/data.pass.cpp
Removed:
################################################################################
diff --git a/libcxx/docs/Status/RangesPaper.csv b/libcxx/docs/Status/RangesPaper.csv
index be82f3fa6d4c1..4ed4f6879a6ee 100644
--- a/libcxx/docs/Status/RangesPaper.csv
+++ b/libcxx/docs/Status/RangesPaper.csv
@@ -97,7 +97,7 @@ Section,Description,Dependencies,Assignee,Complete
| `ranges::ssize <https://llvm.org/D101189>`_
| `ranges::empty <https://llvm.org/D101193>`_
| `ranges::data <https://llvm.org/D101476>`_
-| ranges::cdata",[iterator.concepts],Christopher Di Bella and Zoe Carver,In progress
+| `ranges::cdata <https://llvm.org/D117044>`_",[iterator.concepts],Christopher Di Bella and Zoe Carver,In progress
`[range.range] <http://wg21.link/range.range>`_,"| `ranges::range <https://llvm.org/D100269>`_
| `ranges::borrowed_range <https://llvm.org/D102426>`_
| `ranges::enable_borrowed_range <https://llvm.org/D90999>`_
@@ -114,12 +114,12 @@ Section,Description,Dependencies,Assignee,Complete
`[range.view] <http://wg21.link/range.view>`_,"| `ranges::enable_view <https://llvm.org/D101547>`_
| `ranges::view_base <https://llvm.org/D101547>`_
| `ranges::view <https://llvm.org/D101547>`_",[range.range],Louis Dionne,✅
-`[range.refinements] <http://wg21.link/range.refinements>`_,"| ranges::output_range
+`[range.refinements] <http://wg21.link/range.refinements>`_,"| `ranges::output_range <https://llvm.org/D106704>`_
| `ranges::input_range <https://llvm.org/D100271>`_
| `ranges::forward_range: `D100275 <https://llvm.org/D100275>`_
| `ranges::bidirectional_range <https://llvm.org/D100278>`_
| `ranges::random_access_range <https://llvm.org/D101316>`_
-| ranges::contiguous_range
+| `ranges::contiguous_range <https://llvm.org/D104262>`_
| `ranges::common_range <https://llvm.org/D100269>`_",[range.range],Christopher Di Bella,✅
`[range.refinements]`_,`ranges::viewable_range <https://llvm.org/D105816>`_,[range.range],Louis Dionne,✅
`[range.utility.helpers] <http://wg21.link/range.utility.helpers>`_,"| *simple-view*
diff --git a/libcxx/include/__ranges/data.h b/libcxx/include/__ranges/data.h
index 20d84912d2786..69dfd479c0110 100644
--- a/libcxx/include/__ranges/data.h
+++ b/libcxx/include/__ranges/data.h
@@ -71,6 +71,34 @@ inline namespace __cpo {
} // namespace __cpo
} // namespace ranges
+// [range.prim.cdata]
+
+namespace ranges {
+namespace __cdata {
+ struct __fn {
+ template <class _Tp>
+ requires is_lvalue_reference_v<_Tp&&>
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI
+ constexpr auto operator()(_Tp&& __t) const
+ noexcept(noexcept(ranges::data(static_cast<const remove_reference_t<_Tp>&>(__t))))
+ -> decltype( ranges::data(static_cast<const remove_reference_t<_Tp>&>(__t)))
+ { return ranges::data(static_cast<const remove_reference_t<_Tp>&>(__t)); }
+
+ template <class _Tp>
+ requires is_rvalue_reference_v<_Tp&&>
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI
+ constexpr auto operator()(_Tp&& __t) const
+ noexcept(noexcept(ranges::data(static_cast<const _Tp&&>(__t))))
+ -> decltype( ranges::data(static_cast<const _Tp&&>(__t)))
+ { return ranges::data(static_cast<const _Tp&&>(__t)); }
+ };
+}
+
+inline namespace __cpo {
+ inline constexpr auto cdata = __cdata::__fn{};
+} // namespace __cpo
+} // namespace ranges
+
#endif // !defined(_LIBCPP_HAS_NO_RANGES)
_LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/test/std/library/description/conventions/customization.point.object/cpo.compile.pass.cpp b/libcxx/test/std/library/description/conventions/customization.point.object/cpo.compile.pass.cpp
index 86ddfdeacd921..4cd461631838d 100644
--- a/libcxx/test/std/library/description/conventions/customization.point.object/cpo.compile.pass.cpp
+++ b/libcxx/test/std/library/description/conventions/customization.point.object/cpo.compile.pass.cpp
@@ -61,7 +61,7 @@ static_assert(test(std::weak_order, 1, 2));
static_assert(test(std::ranges::begin, a));
static_assert(test(std::ranges::end, a));
static_assert(test(std::ranges::cbegin, a));
-//static_assert(test(std::ranges::cdata, a));
+static_assert(test(std::ranges::cdata, a));
static_assert(test(std::ranges::cend, a));
//static_assert(test(std::ranges::crbegin, a));
//static_assert(test(std::ranges::crend, a));
diff --git a/libcxx/test/std/ranges/range.access/data.pass.cpp b/libcxx/test/std/ranges/range.access/data.pass.cpp
index 8f2446287a30a..d7d87e2eb0415 100644
--- a/libcxx/test/std/ranges/range.access/data.pass.cpp
+++ b/libcxx/test/std/ranges/range.access/data.pass.cpp
@@ -20,6 +20,7 @@
#include "test_iterators.h"
using RangeDataT = decltype(std::ranges::data);
+using RangeCDataT = decltype(std::ranges::cdata);
static int globalBuff[2];
@@ -32,6 +33,13 @@ static_assert(!std::is_invocable_v<RangeDataT, int [1]>);
static_assert(!std::is_invocable_v<RangeDataT, int (&&)[1]>);
static_assert( std::is_invocable_v<RangeDataT, int (&)[1]>);
+static_assert(!std::is_invocable_v<RangeCDataT, Incomplete[]>);
+static_assert(!std::is_invocable_v<RangeCDataT, Incomplete(&&)[2]>);
+static_assert(!std::is_invocable_v<RangeCDataT, Incomplete(&&)[2][2]>);
+static_assert(!std::is_invocable_v<RangeCDataT, int [1]>);
+static_assert(!std::is_invocable_v<RangeCDataT, int (&&)[1]>);
+static_assert( std::is_invocable_v<RangeCDataT, int (&)[1]>);
+
struct DataMember {
int x;
constexpr const int *data() const { return &x; }
@@ -40,15 +48,21 @@ static_assert( std::is_invocable_v<RangeDataT, DataMember &>);
static_assert(!std::is_invocable_v<RangeDataT, DataMember &&>);
static_assert( std::is_invocable_v<RangeDataT, DataMember const&>);
static_assert(!std::is_invocable_v<RangeDataT, DataMember const&&>);
+static_assert( std::is_invocable_v<RangeCDataT, DataMember &>);
+static_assert(!std::is_invocable_v<RangeCDataT, DataMember &&>);
+static_assert( std::is_invocable_v<RangeCDataT, DataMember const&>);
+static_assert(!std::is_invocable_v<RangeCDataT, DataMember const&&>);
constexpr bool testReturnTypes() {
{
int *x[2];
ASSERT_SAME_TYPE(decltype(std::ranges::data(x)), int**);
+ ASSERT_SAME_TYPE(decltype(std::ranges::cdata(x)), int* const*);
}
{
int x[2][2];
ASSERT_SAME_TYPE(decltype(std::ranges::data(x)), int(*)[2]);
+ ASSERT_SAME_TYPE(decltype(std::ranges::cdata(x)), const int(*)[2]);
}
{
struct D {
@@ -59,6 +73,10 @@ constexpr bool testReturnTypes() {
static_assert(!std::is_invocable_v<RangeDataT, D&&>);
ASSERT_SAME_TYPE(decltype(std::ranges::data(std::declval<const D&>())), short*);
static_assert(!std::is_invocable_v<RangeDataT, const D&&>);
+ ASSERT_SAME_TYPE(decltype(std::ranges::cdata(std::declval<D&>())), short*);
+ static_assert(!std::is_invocable_v<RangeCDataT, D&&>);
+ ASSERT_SAME_TYPE(decltype(std::ranges::cdata(std::declval<const D&>())), short*);
+ static_assert(!std::is_invocable_v<RangeCDataT, const D&&>);
}
{
struct NC {
@@ -72,6 +90,10 @@ constexpr bool testReturnTypes() {
static_assert(!std::is_invocable_v<RangeDataT, NC&&>);
ASSERT_SAME_TYPE(decltype(std::ranges::data(std::declval<const NC&>())), char*);
static_assert(!std::is_invocable_v<RangeDataT, const NC&&>);
+ ASSERT_SAME_TYPE(decltype(std::ranges::cdata(std::declval<NC&>())), char*);
+ static_assert(!std::is_invocable_v<RangeCDataT, NC&&>);
+ ASSERT_SAME_TYPE(decltype(std::ranges::cdata(std::declval<const NC&>())), char*);
+ static_assert(!std::is_invocable_v<RangeCDataT, const NC&&>);
}
return true;
}
@@ -80,12 +102,14 @@ struct VoidDataMember {
void *data() const;
};
static_assert(!std::is_invocable_v<RangeDataT, VoidDataMember const&>);
+static_assert(!std::is_invocable_v<RangeCDataT, VoidDataMember const&>);
struct Empty { };
struct EmptyDataMember {
Empty data() const;
};
static_assert(!std::is_invocable_v<RangeDataT, EmptyDataMember const&>);
+static_assert(!std::is_invocable_v<RangeCDataT, EmptyDataMember const&>);
struct PtrConvertibleDataMember {
struct Ptr {
@@ -94,6 +118,7 @@ struct PtrConvertibleDataMember {
Ptr data() const;
};
static_assert(!std::is_invocable_v<RangeDataT, PtrConvertibleDataMember const&>);
+static_assert(!std::is_invocable_v<RangeCDataT, PtrConvertibleDataMember const&>);
struct NonConstDataMember {
int x;
@@ -115,15 +140,19 @@ struct DataMemberAndBegin {
constexpr bool testDataMember() {
DataMember a;
assert(std::ranges::data(a) == &a.x);
+ assert(std::ranges::cdata(a) == &a.x);
NonConstDataMember b;
assert(std::ranges::data(b) == &b.x);
+ static_assert(!std::is_invocable_v<RangeCDataT, decltype((b))>);
EnabledBorrowingDataMember c;
assert(std::ranges::data(std::move(c)) == &globalBuff[0]);
+ static_assert(!std::is_invocable_v<RangeCDataT, decltype(std::move(c))>);
DataMemberAndBegin d;
assert(std::ranges::data(d) == &d.x);
+ assert(std::ranges::cdata(d) == &d.x);
return true;
}
@@ -139,6 +168,10 @@ static_assert( std::is_invocable_v<RangeDataT, BeginMemberContiguousIterator &>)
static_assert(!std::is_invocable_v<RangeDataT, BeginMemberContiguousIterator &&>);
static_assert( std::is_invocable_v<RangeDataT, BeginMemberContiguousIterator const&>);
static_assert(!std::is_invocable_v<RangeDataT, BeginMemberContiguousIterator const&&>);
+static_assert( std::is_invocable_v<RangeCDataT, BeginMemberContiguousIterator &>);
+static_assert(!std::is_invocable_v<RangeCDataT, BeginMemberContiguousIterator &&>);
+static_assert( std::is_invocable_v<RangeCDataT, BeginMemberContiguousIterator const&>);
+static_assert(!std::is_invocable_v<RangeCDataT, BeginMemberContiguousIterator const&&>);
struct BeginMemberRandomAccess {
int buff[8];
@@ -149,6 +182,10 @@ static_assert(!std::is_invocable_v<RangeDataT, BeginMemberRandomAccess&>);
static_assert(!std::is_invocable_v<RangeDataT, BeginMemberRandomAccess&&>);
static_assert(!std::is_invocable_v<RangeDataT, const BeginMemberRandomAccess&>);
static_assert(!std::is_invocable_v<RangeDataT, const BeginMemberRandomAccess&&>);
+static_assert(!std::is_invocable_v<RangeCDataT, BeginMemberRandomAccess&>);
+static_assert(!std::is_invocable_v<RangeCDataT, BeginMemberRandomAccess&&>);
+static_assert(!std::is_invocable_v<RangeCDataT, const BeginMemberRandomAccess&>);
+static_assert(!std::is_invocable_v<RangeCDataT, const BeginMemberRandomAccess&&>);
struct BeginFriendContiguousIterator {
int buff[8];
@@ -161,6 +198,10 @@ static_assert( std::is_invocable_v<RangeDataT, BeginMemberContiguousIterator &>)
static_assert(!std::is_invocable_v<RangeDataT, BeginMemberContiguousIterator &&>);
static_assert( std::is_invocable_v<RangeDataT, BeginMemberContiguousIterator const&>);
static_assert(!std::is_invocable_v<RangeDataT, BeginMemberContiguousIterator const&&>);
+static_assert( std::is_invocable_v<RangeCDataT, BeginMemberContiguousIterator &>);
+static_assert(!std::is_invocable_v<RangeCDataT, BeginMemberContiguousIterator &&>);
+static_assert( std::is_invocable_v<RangeCDataT, BeginMemberContiguousIterator const&>);
+static_assert(!std::is_invocable_v<RangeCDataT, BeginMemberContiguousIterator const&&>);
struct BeginFriendRandomAccess {
friend random_access_iterator<const int*> begin(const BeginFriendRandomAccess iter);
@@ -169,6 +210,10 @@ static_assert(!std::is_invocable_v<RangeDataT, BeginFriendRandomAccess&>);
static_assert(!std::is_invocable_v<RangeDataT, BeginFriendRandomAccess&&>);
static_assert(!std::is_invocable_v<RangeDataT, const BeginFriendRandomAccess&>);
static_assert(!std::is_invocable_v<RangeDataT, const BeginFriendRandomAccess&&>);
+static_assert(!std::is_invocable_v<RangeCDataT, BeginFriendRandomAccess&>);
+static_assert(!std::is_invocable_v<RangeCDataT, BeginFriendRandomAccess&&>);
+static_assert(!std::is_invocable_v<RangeCDataT, const BeginFriendRandomAccess&>);
+static_assert(!std::is_invocable_v<RangeCDataT, const BeginFriendRandomAccess&&>);
struct BeginMemberRvalue {
int buff[8];
@@ -179,6 +224,10 @@ static_assert(!std::is_invocable_v<RangeDataT, BeginMemberRvalue&>);
static_assert(!std::is_invocable_v<RangeDataT, BeginMemberRvalue&&>);
static_assert(!std::is_invocable_v<RangeDataT, BeginMemberRvalue const&>);
static_assert(!std::is_invocable_v<RangeDataT, BeginMemberRvalue const&&>);
+static_assert(!std::is_invocable_v<RangeCDataT, BeginMemberRvalue&>);
+static_assert(!std::is_invocable_v<RangeCDataT, BeginMemberRvalue&&>);
+static_assert(!std::is_invocable_v<RangeCDataT, BeginMemberRvalue const&>);
+static_assert(!std::is_invocable_v<RangeCDataT, BeginMemberRvalue const&&>);
struct BeginMemberBorrowingEnabled {
constexpr contiguous_iterator<int*> begin() { return contiguous_iterator<int*>{&globalBuff[1]}; }
@@ -189,19 +238,27 @@ static_assert( std::is_invocable_v<RangeDataT, BeginMemberBorrowingEnabled &>);
static_assert( std::is_invocable_v<RangeDataT, BeginMemberBorrowingEnabled &&>);
static_assert(!std::is_invocable_v<RangeDataT, BeginMemberBorrowingEnabled const&>);
static_assert(!std::is_invocable_v<RangeDataT, BeginMemberBorrowingEnabled const&&>);
+static_assert(!std::is_invocable_v<RangeCDataT, BeginMemberBorrowingEnabled &>);
+static_assert(!std::is_invocable_v<RangeCDataT, BeginMemberBorrowingEnabled &&>);
+static_assert(!std::is_invocable_v<RangeCDataT, BeginMemberBorrowingEnabled const&>);
+static_assert(!std::is_invocable_v<RangeCDataT, BeginMemberBorrowingEnabled const&&>);
constexpr bool testViaRangesBegin() {
int arr[2];
assert(std::ranges::data(arr) == arr + 0);
+ assert(std::ranges::cdata(arr) == arr + 0);
BeginMemberContiguousIterator a;
assert(std::ranges::data(a) == a.buff);
+ assert(std::ranges::cdata(a) == a.buff);
const BeginFriendContiguousIterator b {};
assert(std::ranges::data(b) == b.buff);
+ assert(std::ranges::cdata(b) == b.buff);
BeginMemberBorrowingEnabled c;
assert(std::ranges::data(std::move(c)) == &globalBuff[1]);
+ static_assert(!std::is_invocable_v<RangeCDataT, decltype(std::move(c))>);
return true;
}
@@ -211,6 +268,8 @@ struct Incomplete;
template<class T> struct Holder { T t; };
static_assert(!std::is_invocable_v<RangeDataT, Holder<Incomplete>*>);
static_assert(!std::is_invocable_v<RangeDataT, Holder<Incomplete>*&>);
+static_assert(!std::is_invocable_v<RangeCDataT, Holder<Incomplete>*>);
+static_assert(!std::is_invocable_v<RangeCDataT, Holder<Incomplete>*&>);
struct RandomButNotContiguous {
random_access_iterator<int*> begin() const;
@@ -218,6 +277,8 @@ struct RandomButNotContiguous {
};
static_assert(!std::is_invocable_v<RangeDataT, RandomButNotContiguous>);
static_assert(!std::is_invocable_v<RangeDataT, RandomButNotContiguous&>);
+static_assert(!std::is_invocable_v<RangeCDataT, RandomButNotContiguous>);
+static_assert(!std::is_invocable_v<RangeCDataT, RandomButNotContiguous&>);
int main(int, char**) {
static_assert(testReturnTypes());
More information about the libcxx-commits
mailing list