[libcxx-commits] [libcxx] [libcxx] P2278R4: implement `{basic_, }const_iterator`, and have `cbegin` et. al. return it (PR #99915)

Louis Dionne via libcxx-commits libcxx-commits at lists.llvm.org
Thu Aug 29 12:46:27 PDT 2024


================
@@ -0,0 +1,207 @@
+//===----------------------------------------------------------------------===//
+//
+// 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, c++20
+
+// std::ranges::cbegin
+// std::ranges::crbegin
+
+#include <ranges>
+
+#include <cassert>
+#include <utility>
+#include "almost_satisfies_types.h"
+#include "test_macros.h"
+#include "test_iterators.h"
+
+using RangeCBeginT  = decltype(std::ranges::cbegin);
+using RangeCRBeginT = decltype(std::ranges::crbegin);
+
+static_assert(!std::is_invocable_v<RangeCBeginT, int (&&)[10]>);
+static_assert(std::is_invocable_v<RangeCBeginT, int (&)[10]>);
+static_assert(!std::is_invocable_v<RangeCBeginT, int (&&)[]>);
+static_assert(!std::is_invocable_v<RangeCBeginT, int (&)[]>);
+static_assert(!std::is_invocable_v<RangeCRBeginT, int (&&)[10]>);
+static_assert(std::is_invocable_v<RangeCRBeginT, int (&)[10]>);
+static_assert(!std::is_invocable_v<RangeCRBeginT, int (&&)[]>);
+static_assert(!std::is_invocable_v<RangeCRBeginT, int (&)[]>);
+
+static_assert(!std::is_invocable_v<RangeCBeginT, InputRangeNotDerivedFrom>);
+static_assert(!std::is_invocable_v<RangeCBeginT, InputRangeNotIndirectlyReadable>);
+static_assert(!std::is_invocable_v<RangeCBeginT, InputRangeNotInputOrOutputIterator>);
+static_assert(!std::is_invocable_v<RangeCBeginT, InputRangeNotSentinelSemiregular>);
+static_assert(!std::is_invocable_v<RangeCBeginT, InputRangeNotSentinelEqualityComparableWith>);
+
+static_assert(!std::is_invocable_v<RangeCRBeginT, BidirectionalRangeNotDerivedFrom>);
+static_assert(!std::is_invocable_v<RangeCRBeginT, BidirectionalRangeNotSentinelSemiregular>);
+static_assert(!std::is_invocable_v<RangeCRBeginT, BidirectionalRangeNotSentinelWeaklyEqualityComparableWith>);
+static_assert(!std::is_invocable_v<RangeCRBeginT, BidirectionalRangeNotDecrementable>);
+
+struct Incomplete;
+
+static_assert(!std::is_invocable_v<RangeCBeginT, Incomplete (&&)[]>);
+static_assert(!std::is_invocable_v<RangeCBeginT, const Incomplete (&&)[]>);
+static_assert(!std::is_invocable_v<RangeCBeginT, Incomplete (&&)[10]>);
+static_assert(!std::is_invocable_v<RangeCBeginT, const Incomplete (&&)[10]>);
+
+static_assert(!std::is_invocable_v<RangeCRBeginT, Incomplete (&&)[]>);
+static_assert(!std::is_invocable_v<RangeCRBeginT, const Incomplete (&&)[]>);
+static_assert(!std::is_invocable_v<RangeCRBeginT, Incomplete (&&)[10]>);
+static_assert(!std::is_invocable_v<RangeCRBeginT, const Incomplete (&&)[10]>);
+
+// This case is IFNDR; we handle it SFINAE-friendly.
+LIBCPP_STATIC_ASSERT(!std::is_invocable_v<RangeCBeginT, Incomplete (&)[]>);
+LIBCPP_STATIC_ASSERT(!std::is_invocable_v<RangeCBeginT, const Incomplete (&)[]>);
+LIBCPP_STATIC_ASSERT(!std::is_invocable_v<RangeCRBeginT, Incomplete (&)[]>);
+LIBCPP_STATIC_ASSERT(!std::is_invocable_v<RangeCRBeginT, const Incomplete (&)[]>);
+
+// This case is IFNDR; we handle it SFINAE-friendly.
+LIBCPP_STATIC_ASSERT(!std::is_invocable_v<RangeCBeginT, Incomplete (&)[10]>);
+LIBCPP_STATIC_ASSERT(!std::is_invocable_v<RangeCBeginT, const Incomplete (&)[10]>);
+LIBCPP_STATIC_ASSERT(!std::is_invocable_v<RangeCRBeginT, Incomplete (&)[10]>);
+LIBCPP_STATIC_ASSERT(!std::is_invocable_v<RangeCRBeginT, const Incomplete (&)[10]>);
+
+struct NonborrowingRange {
+  int x;
+  constexpr const int* begin() const { return &x; }
+  constexpr const int* rbegin() const { return &x; }
+  constexpr const int* end() const { return &x; }
+  constexpr const int* rend() const { return &x; }
+};
+
+// Ensure that we can't call with rvalues with borrowing disabled.
+static_assert(std::is_invocable_v<RangeCBeginT, NonborrowingRange&>);
+static_assert(!std::is_invocable_v<RangeCBeginT, NonborrowingRange&&>);
+static_assert(std::is_invocable_v<RangeCBeginT, NonborrowingRange const&>);
+static_assert(!std::is_invocable_v<RangeCBeginT, NonborrowingRange const&&>);
+static_assert(std::is_invocable_v<RangeCRBeginT, NonborrowingRange&>);
+static_assert(!std::is_invocable_v<RangeCRBeginT, NonborrowingRange&&>);
+static_assert(std::is_invocable_v<RangeCRBeginT, NonborrowingRange const&>);
+static_assert(!std::is_invocable_v<RangeCRBeginT, NonborrowingRange const&&>);
+
+constexpr bool testReturnTypes() {
+  int* a[2];
+  int b[2][2];
+  struct PossiblyConstRange {
+    char*& begin();
+    char*& end();
+    const short*& begin() const;
+    const short*& end() const;
+    int*& rbegin();
+    int*& rend();
+    const long*& rbegin() const;
+    const long*& rend() const;
+  } c;
+  struct AlwaysConstRange {
+    const char*& begin();
+    const char*& end();
+    const short*& begin() const;
+    const short*& end() const;
+    const int*& rbegin();
+    const int*& rend();
+    const long*& rbegin() const;
+    const long*& rend() const;
+  } d;
+  struct NeverConstRange {
+    char*& begin();
+    char*& end();
+    short*& begin() const;
+    short& end() const;
+    int*& rbegin();
+    int*& rend();
+    long*& rbegin() const;
+    long*& rend() const;
+  } e;
+
+  static_assert(!std::ranges::constant_range<PossiblyConstRange>);
----------------
ldionne wrote:

We should have a test dedicated to this concept, not only the ones here and in `cend.pass.cpp`.

https://github.com/llvm/llvm-project/pull/99915


More information about the libcxx-commits mailing list