[libcxx-commits] [libcxx] 74fd3cb - [libcxx][ranges] implements dangling, borrowed_iterator_t, borrowed_subrange_t

Christopher Di Bella via libcxx-commits libcxx-commits at lists.llvm.org
Wed Jul 21 14:35:12 PDT 2021


Author: Christopher Di Bella
Date: 2021-07-21T21:34:13Z
New Revision: 74fd3cb8cd3ea41219d522412f4408d9993352ef

URL: https://github.com/llvm/llvm-project/commit/74fd3cb8cd3ea41219d522412f4408d9993352ef
DIFF: https://github.com/llvm/llvm-project/commit/74fd3cb8cd3ea41219d522412f4408d9993352ef.diff

LOG: [libcxx][ranges] implements dangling, borrowed_iterator_t, borrowed_subrange_t

* Implements part of P0896 'The One Ranges Proposal'
* Implements http://wg21.link/range.dangling

Reviewed By: zoecarver

Differential Revision: https://reviews.llvm.org/D105205

Added: 
    libcxx/include/__ranges/dangling.h
    libcxx/test/libcxx/diagnostics/detail.headers/ranges/dangling.module.verify.cpp
    libcxx/test/std/ranges/range.utility/range.dangling/borrowed_iterator.compile.pass.cpp
    libcxx/test/std/ranges/range.utility/range.dangling/borrowed_subrange.compile.pass.cpp
    libcxx/test/std/ranges/range.utility/range.dangling/dangling.pass.cpp

Modified: 
    libcxx/docs/Status/RangesPaper.csv
    libcxx/include/CMakeLists.txt
    libcxx/include/__ranges/subrange.h
    libcxx/include/module.modulemap
    libcxx/include/ranges

Removed: 
    


################################################################################
diff  --git a/libcxx/docs/Status/RangesPaper.csv b/libcxx/docs/Status/RangesPaper.csv
index 3fadfc3f15fa..02c764c8e8bc 100644
--- a/libcxx/docs/Status/RangesPaper.csv
+++ b/libcxx/docs/Status/RangesPaper.csv
@@ -133,7 +133,7 @@ Section,Description,Dependencies,Assignee,Complete
 `[range.dangling] <http://wg21.link/range.dangling>`_,"| ranges::dangling
 | ranges::borrowed_iterator_t
 | ranges::borrowed_subrange_t","| [range.range]
-| [range.subrange]",Unassigned,Not started
+| [range.subrange]",Christopher Di Bella,✅
 `[range.all] <http://wg21.link/range.all>`_,`view::all <https://llvm.org/D102028>`_,"[range.subrange], [range.view.ref]",Zoe Carver,✅
 `[range.view.ref] <http://wg21.link/range.view>`_,`ref-view <https://llvm.org/D102020>`_,[view.interface],Zoe Carver,✅
 `[range.filter] <http://wg21.link/range.filter>`_,filter_view,[range.all],Louis Dionne,Not started

diff  --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index fd86cf114822..007d3f6a4c5b 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -186,6 +186,7 @@ set(files
   __ranges/all.h
   __ranges/concepts.h
   __ranges/copyable_box.h
+  __ranges/dangling.h
   __ranges/data.h
   __ranges/drop_view.h
   __ranges/empty_view.h

diff  --git a/libcxx/include/__ranges/dangling.h b/libcxx/include/__ranges/dangling.h
new file mode 100644
index 000000000000..deb02a1a448d
--- /dev/null
+++ b/libcxx/include/__ranges/dangling.h
@@ -0,0 +1,47 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP___RANGES_DANGLING_H
+#define _LIBCPP___RANGES_DANGLING_H
+
+#include <__config>
+#include <__ranges/access.h>
+#include <__ranges/concepts.h>
+#include <type_traits>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#pragma GCC system_header
+#endif
+
+_LIBCPP_PUSH_MACROS
+#include <__undef_macros>
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+#if !defined(_LIBCPP_HAS_NO_RANGES)
+
+namespace ranges {
+struct dangling {
+  dangling() = default;
+  _LIBCPP_HIDE_FROM_ABI constexpr dangling(auto&&...) noexcept {}
+};
+
+template <range _Rp>
+using borrowed_iterator_t = _If<borrowed_range<_Rp>, iterator_t<_Rp>, dangling>;
+
+// borrowed_subrange_t defined in <__ranges/subrange.h>
+} // namespace ranges
+
+#endif // !_LIBCPP_HAS_NO_RANGES
+
+_LIBCPP_END_NAMESPACE_STD
+
+_LIBCPP_POP_MACROS
+
+#endif // _LIBCPP___RANGES_DANGLING_H

diff  --git a/libcxx/include/__ranges/subrange.h b/libcxx/include/__ranges/subrange.h
index e3ed8657583f..25d333db02de 100644
--- a/libcxx/include/__ranges/subrange.h
+++ b/libcxx/include/__ranges/subrange.h
@@ -16,6 +16,7 @@
 #include <__iterator/advance.h>
 #include <__ranges/access.h>
 #include <__ranges/concepts.h>
+#include <__ranges/dangling.h>
 #include <__ranges/enable_borrowed_range.h>
 #include <__ranges/size.h>
 #include <__ranges/view_interface.h>
@@ -248,6 +249,9 @@ namespace ranges {
 
   template<class _Ip, class _Sp, subrange_kind _Kp>
   inline constexpr bool enable_borrowed_range<subrange<_Ip, _Sp, _Kp>> = true;
+
+  template<range _Rp>
+  using borrowed_subrange_t = _If<borrowed_range<_Rp>, subrange<iterator_t<_Rp> >, dangling>;
 } // namespace ranges
 
 using ranges::get;

diff  --git a/libcxx/include/module.modulemap b/libcxx/include/module.modulemap
index ecd853c8536b..69316985467e 100644
--- a/libcxx/include/module.modulemap
+++ b/libcxx/include/module.modulemap
@@ -606,6 +606,7 @@ module std [system] {
       module all                    { private header "__ranges/all.h"                   }
       module concepts               { private header "__ranges/concepts.h"              }
       module copyable_box           { private header "__ranges/copyable_box.h"          }
+      module dangling               { private header "__ranges/dangling.h"              }
       module data                   { private header "__ranges/data.h"                  }
       module drop_view              { private header "__ranges/drop_view.h"             }
       module empty                  { private header "__ranges/empty.h"                 }

diff  --git a/libcxx/include/ranges b/libcxx/include/ranges
index 367ad60226d4..45825fde7293 100644
--- a/libcxx/include/ranges
+++ b/libcxx/include/ranges
@@ -103,6 +103,15 @@ namespace std::ranges {
   template<class I, class S, subrange_kind K>
     inline constexpr bool enable_borrowed_range<subrange<I, S, K>> = true;
 
+  // [range.dangling], dangling iterator handling
+  struct dangling;
+
+  template<range R>
+    using borrowed_iterator_t = see below;
+
+  template<range R>
+    using borrowed_subrange_t = see below;
+
   // [range.empty], empty view
   template<class T>
     requires is_object_v<T>
@@ -145,6 +154,7 @@ namespace std::ranges {
 #include <__ranges/access.h>
 #include <__ranges/all.h>
 #include <__ranges/concepts.h>
+#include <__ranges/dangling.h>
 #include <__ranges/data.h>
 #include <__ranges/drop_view.h>
 #include <__ranges/empty.h>

diff  --git a/libcxx/test/libcxx/diagnostics/detail.headers/ranges/dangling.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/ranges/dangling.module.verify.cpp
new file mode 100644
index 000000000000..5f4fa40cac61
--- /dev/null
+++ b/libcxx/test/libcxx/diagnostics/detail.headers/ranges/dangling.module.verify.cpp
@@ -0,0 +1,16 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// 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: modules-build
+
+// WARNING: This test was generated by 'generate_private_header_tests.py'
+// and should not be edited manually.
+
+// expected-error@*:* {{use of private header from outside its module: '__ranges/dangling.h'}}
+#include <__ranges/dangling.h>

diff  --git a/libcxx/test/std/ranges/range.utility/range.dangling/borrowed_iterator.compile.pass.cpp b/libcxx/test/std/ranges/range.utility/range.dangling/borrowed_iterator.compile.pass.cpp
new file mode 100644
index 000000000000..bff34a75c834
--- /dev/null
+++ b/libcxx/test/std/ranges/range.utility/range.dangling/borrowed_iterator.compile.pass.cpp
@@ -0,0 +1,36 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+
+// std::ranges::borrowed_iterator_t;
+
+#include <ranges>
+
+#include <concepts>
+#include <span>
+#include <string>
+#include <string_view>
+#include <vector>
+
+static_assert(std::same_as<std::ranges::borrowed_iterator_t<std::string>, std::ranges::dangling>);
+static_assert(std::same_as<std::ranges::borrowed_iterator_t<std::string&&>, std::ranges::dangling>);
+static_assert(std::same_as<std::ranges::borrowed_iterator_t<std::vector<int> >, std::ranges::dangling>);
+
+static_assert(std::same_as<std::ranges::borrowed_iterator_t<std::string&>, std::string::iterator>);
+static_assert(std::same_as<std::ranges::borrowed_iterator_t<std::string_view>, std::string_view::iterator>);
+static_assert(std::same_as<std::ranges::borrowed_iterator_t<std::span<int> >, std::span<int>::iterator>);
+
+template <class T>
+constexpr bool has_borrowed_iterator = requires {
+  typename std::ranges::borrowed_iterator_t<T>;
+};
+
+static_assert(!has_borrowed_iterator<int>);

diff  --git a/libcxx/test/std/ranges/range.utility/range.dangling/borrowed_subrange.compile.pass.cpp b/libcxx/test/std/ranges/range.utility/range.dangling/borrowed_subrange.compile.pass.cpp
new file mode 100644
index 000000000000..73271450e5f1
--- /dev/null
+++ b/libcxx/test/std/ranges/range.utility/range.dangling/borrowed_subrange.compile.pass.cpp
@@ -0,0 +1,44 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+
+// std::ranges::borrowed_subrange_t;
+
+#include <ranges>
+
+#include <concepts>
+#include <span>
+#include <string>
+#include <string_view>
+#include <vector>
+
+static_assert(std::same_as<std::ranges::borrowed_subrange_t<std::string>, std::ranges::dangling>);
+static_assert(std::same_as<std::ranges::borrowed_subrange_t<std::string&&>, std::ranges::dangling>);
+static_assert(std::same_as<std::ranges::borrowed_subrange_t<std::vector<int> >, std::ranges::dangling>);
+
+static_assert(
+    std::same_as<std::ranges::borrowed_subrange_t<std::string&>, std::ranges::subrange<std::string::iterator> >);
+
+static_assert(
+    std::same_as<std::ranges::borrowed_subrange_t<std::span<int> >, std::ranges::subrange<std::span<int>::iterator> >);
+
+static_assert(std::same_as<std::ranges::borrowed_subrange_t<std::string_view>,
+                           std::ranges::subrange<std::string_view::iterator> >);
+
+template <class T>
+constexpr bool has_type = requires {
+  typename std::ranges::borrowed_subrange_t<T>;
+};
+
+static_assert(!has_type<int>);
+
+struct S {};
+static_assert(!has_type<S>);

diff  --git a/libcxx/test/std/ranges/range.utility/range.dangling/dangling.pass.cpp b/libcxx/test/std/ranges/range.utility/range.dangling/dangling.pass.cpp
new file mode 100644
index 000000000000..b04d823c31c0
--- /dev/null
+++ b/libcxx/test/std/ranges/range.utility/range.dangling/dangling.pass.cpp
@@ -0,0 +1,40 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+
+// std::ranges::dangling;
+
+#include <ranges>
+
+#include <concepts>
+#include <type_traits>
+
+static_assert(std::is_empty_v<std::ranges::dangling>);
+
+template<int> struct S { };
+static_assert(std::is_nothrow_constructible_v<std::ranges::dangling>);
+static_assert(std::is_nothrow_constructible_v<std::ranges::dangling, S<0>>);
+static_assert(std::is_nothrow_constructible_v<std::ranges::dangling, S<0>, S<1>>);
+static_assert(std::is_nothrow_constructible_v<std::ranges::dangling, S<0>, S<1>, S<2>>);
+
+constexpr bool test_dangling() {
+  [[maybe_unused]] auto a = std::ranges::dangling();
+  [[maybe_unused]] auto b = std::ranges::dangling(S<0>());
+  [[maybe_unused]] auto c = std::ranges::dangling(S<0>(), S<1>());
+  [[maybe_unused]] auto d = std::ranges::dangling(S<0>(), S<1>(), S<2>());
+  return true;
+}
+
+int main(int, char**) {
+  static_assert(test_dangling());
+  test_dangling();
+  return 0;
+}


        


More information about the libcxx-commits mailing list