[libcxx-commits] [libcxx] 9816d43 - [libcxx] adds `iter_difference_t` and `iter_value_t`

Christopher Di Bella via libcxx-commits libcxx-commits at lists.llvm.org
Tue Apr 20 12:02:24 PDT 2021


Author: Christopher Di Bella
Date: 2021-04-20T19:02:07Z
New Revision: 9816d43cff5ad7abb94eab94dcd205285675972a

URL: https://github.com/llvm/llvm-project/commit/9816d43cff5ad7abb94eab94dcd205285675972a
DIFF: https://github.com/llvm/llvm-project/commit/9816d43cff5ad7abb94eab94dcd205285675972a.diff

LOG: [libcxx] adds `iter_difference_t` and `iter_value_t`

Implements parts of:
    * P0896R4 The One Ranges Proposal

Depends on D99855.

Reviewed By: ldionne, #libc

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

Added: 
    libcxx/test/std/iterators/iterator.requirements/iterator.assoc.types/incrementable.traits/iter_difference_t.pass.cpp
    libcxx/test/std/iterators/iterator.requirements/iterator.assoc.types/readable.traits/iter_value_t.pass.cpp

Modified: 
    libcxx/docs/OneRangesProposalStatus.csv
    libcxx/include/__iterator/incrementable_traits.h
    libcxx/include/__iterator/readable_traits.h
    libcxx/include/iterator

Removed: 
    


################################################################################
diff  --git a/libcxx/docs/OneRangesProposalStatus.csv b/libcxx/docs/OneRangesProposalStatus.csv
index 645047d0ddfa..822b09c4a9bd 100644
--- a/libcxx/docs/OneRangesProposalStatus.csv
+++ b/libcxx/docs/OneRangesProposalStatus.csv
@@ -3,13 +3,13 @@ Section,Description,Dependencies,Assignee,Patch,Complete
 [tuple.helper],Update <tuple> includes.,,,,
 [function.objects],"Comparison functions: equal_to, less, etc.",[concepts],Zoe Carver,`D100429 <https://reviews.llvm.org/D100429>`_,
 [memory.syn],Add specializations for uninitialized_* and destroy_*. ,"[concepts], [readable.traits]: iter_value_t",,,
-[readable.traits]: indirectly_readable_traits,indirectly_readable_traits only. ,[concepts],Christopher Di Bella,`D99461 <https://reviews.llvm.org/D99461>`_,
-[iterator.traits],Mainly updates to iterator_traits.,"[readable.traits]: indirectly_readable_traits, [concepts]",Christopher Di Bella,"`D99854 <https://reviews.llvm.org/D99854>`_, `D99855 <https://reviews.llvm.org/D99855>`_",
-[readable.traits]: iter_value_t,Finish implementing readable.traits.,"[readable.traits]: indirectly_readable_traits, [concepts], [iterator.traits]",Christopher Di Bella,`D99863 <https://reviews.llvm.org/D99863>`_,
+[readable.traits]: indirectly_readable_traits,indirectly_readable_traits only. ,[concepts],Christopher Di Bella,`D99461 <https://reviews.llvm.org/D99461>`_,✅
+[iterator.traits],Mainly updates to iterator_traits.,"[readable.traits]: indirectly_readable_traits, [concepts]",Christopher Di Bella,"`D99854 <https://reviews.llvm.org/D99854>`_, `D99855 <https://reviews.llvm.org/D99855>`_",✅
+[readable.traits]: iter_value_t,Finish implementing readable.traits.,"[readable.traits]: indirectly_readable_traits, [concepts], [iterator.traits]",Christopher Di Bella,`D99863 <https://reviews.llvm.org/D99863>`_,✅
 [specialized.algorithms],NOT FINISHED,NOT FINISHED,,,
 [strings],Adds begin/end and updates const_iterator.,[iterator.concepts],,,
 [views.span],Same as [strings],[iterator.concepts],,,
-[incrementable.traits],,[concepts],Christopher Di Bella,"`D99141 <https://reviews.llvm.org/D99141>`_, `D99863 <https://reviews.llvm.org/D99863>`_",1/2
+[incrementable.traits],,[concepts],Christopher Di Bella,"`D99141 <https://reviews.llvm.org/D99141>`_, `D99863 <https://reviews.llvm.org/D99863>`_",✅
 [iterator.cust.move],Implement iter_move.,,Christopher Di Bella,`D99873 <https://reviews.llvm.org/D99873>`_,
 [iterator.cust.swap],Implement iter_swap.,"[concepts], [readable.traits]: iter_value_t",,,
 [iterator.concepts],"indirectly_readable, indirectly_writable, weakly_incrementable, incrementable, input_or_output_iterator, sentinel_for, sized_sentinel_for, input_iterator, output_iterator, forward_iterator, bidirectional_iterator, random_access_iterator, and contiguous_iterator.","[concepts], [readable.traits]: iter_value_t, [iterator.traits]",Christopher Di Bella,"indirectly_readable: `D100073 <https://reviews.llvm.org/D100073>`_

diff  --git a/libcxx/include/__iterator/incrementable_traits.h b/libcxx/include/__iterator/incrementable_traits.h
index 2a7dff8cea53..2acabbaa1a9b 100644
--- a/libcxx/include/__iterator/incrementable_traits.h
+++ b/libcxx/include/__iterator/incrementable_traits.h
@@ -12,6 +12,7 @@
 
 #include <__config>
 #include <__iterator/concepts.h>
+#include <type_traits>
 
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
 #pragma GCC system_header
@@ -56,6 +57,17 @@ struct incrementable_traits<_Tp> {
   using 
diff erence_type = make_signed_t<decltype(declval<_Tp>() - declval<_Tp>())>;
 };
 
+template <class>
+struct iterator_traits;
+
+// Let `RI` be `remove_­cvref_­t<I>`. The type `iter_­
diff erence_­t<I>` denotes
+// `incrementable_­traits<RI>::
diff erence_­type` if `iterator_­traits<RI>` names a specialization
+// generated from the primary template, and `iterator_­traits<RI>::
diff erence_­type` otherwise.
+template <class _Ip>
+using iter_
diff erence_t = typename conditional_t<__is_primary_template<iterator_traits<remove_cvref_t<_Ip> > >::value,
+                                                 incrementable_traits<remove_cvref_t<_Ip> >,
+                                                 iterator_traits<remove_cvref_t<_Ip> > >::
diff erence_type;
+
 #endif // !defined(_LIBCPP_HAS_NO_RANGES)
 
 _LIBCPP_END_NAMESPACE_STD

diff  --git a/libcxx/include/__iterator/readable_traits.h b/libcxx/include/__iterator/readable_traits.h
index c2a78e727c8d..8566f869cc14 100644
--- a/libcxx/include/__iterator/readable_traits.h
+++ b/libcxx/include/__iterator/readable_traits.h
@@ -70,6 +70,17 @@ requires __has_member_element_type<_Tp> &&
 struct indirectly_readable_traits<_Tp>
   : __cond_value_type<typename _Tp::value_type> {};
 
+template <class>
+struct iterator_traits;
+
+// Let `RI` be `remove_­cvref_­t<I>`. The type `iter_­value_­t<I>` denotes
+// `indirectly_­readable_­traits<RI>::value_­type` if `iterator_­traits<RI>` names a specialization
+// generated from the primary template, and `iterator_­traits<RI>::value_­type` otherwise.
+template <class _Ip>
+using iter_value_t = typename conditional_t<__is_primary_template<iterator_traits<remove_cvref_t<_Ip> > >::value,
+                                            indirectly_readable_traits<remove_cvref_t<_Ip> >,
+                                            iterator_traits<remove_cvref_t<_Ip> > >::value_type;
+
 #endif // !defined(_LIBCPP_HAS_NO_RANGES)
 
 _LIBCPP_END_NAMESPACE_STD

diff  --git a/libcxx/include/iterator b/libcxx/include/iterator
index a1e492a229a1..2785fec9f756 100644
--- a/libcxx/include/iterator
+++ b/libcxx/include/iterator
@@ -18,7 +18,12 @@
 namespace std
 {
 template<class> struct incrementable_traits;       // since C++20
+template<class T>
+  using iter_
diff erence_t = see below;             // since C++20
+
 template<class> struct indirectly_readable_traits; // since C++20
+template<class T>
+  using iter_value_t = see below;                  // since C++20
 
 template<class Iterator>
 struct iterator_traits;

diff  --git a/libcxx/test/std/iterators/iterator.requirements/iterator.assoc.types/incrementable.traits/iter_
diff erence_t.pass.cpp b/libcxx/test/std/iterators/iterator.requirements/iterator.assoc.types/incrementable.traits/iter_
diff erence_t.pass.cpp
new file mode 100644
index 000000000000..05a06905abcf
--- /dev/null
+++ b/libcxx/test/std/iterators/iterator.requirements/iterator.assoc.types/incrementable.traits/iter_
diff erence_t.pass.cpp
@@ -0,0 +1,70 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+
+// template<class T>
+// using iter_
diff erence_t;
+
+#include <iterator>
+
+#include <concepts>
+#include <vector>
+
+template <class T, class Expected>
+[[nodiscard]] constexpr bool check_iter_
diff erence_t() {
+  constexpr bool result = std::same_as<std::iter_
diff erence_t<T>, Expected>;
+  static_assert(std::same_as<std::iter_
diff erence_t<T const>, Expected> == result);
+  static_assert(std::same_as<std::iter_
diff erence_t<T volatile>, Expected> == result);
+  static_assert(std::same_as<std::iter_
diff erence_t<T const volatile>, Expected> == result);
+  static_assert(std::same_as<std::iter_
diff erence_t<T const&>, Expected> == result);
+  static_assert(std::same_as<std::iter_
diff erence_t<T volatile&>, Expected> == result);
+  static_assert(std::same_as<std::iter_
diff erence_t<T const volatile&>, Expected> == result);
+  static_assert(std::same_as<std::iter_
diff erence_t<T const&&>, Expected> == result);
+  static_assert(std::same_as<std::iter_
diff erence_t<T volatile&&>, Expected> == result);
+  static_assert(std::same_as<std::iter_
diff erence_t<T const volatile&&>, Expected> == result);
+
+  return result;
+}
+
+static_assert(check_iter_
diff erence_t<int, int>());
+static_assert(check_iter_
diff erence_t<int*, std::ptr
diff _t>());
+static_assert(check_iter_
diff erence_t<std::vector<int>::iterator, std::vector<int>::iterator::
diff erence_type>());
+
+struct int_subtraction {
+  friend int operator-(int_subtraction, int_subtraction) noexcept;
+};
+static_assert(check_iter_
diff erence_t<int_subtraction, int>());
+
+// clang-format off
+template <class T>
+requires requires { typename std::iter_
diff erence_t<T>; }
+[[nodiscard]] constexpr bool check_no_iter_
diff erence_t() {
+  return false;
+}
+// clang-format on
+
+template <class T>
+[[nodiscard]] constexpr bool check_no_iter_
diff erence_t() {
+  return true;
+}
+
+static_assert(check_no_iter_
diff erence_t<void>());
+static_assert(check_no_iter_
diff erence_t<double>());
+
+struct S {};
+static_assert(check_no_iter_
diff erence_t<S>());
+
+struct void_subtraction {
+  friend void operator-(void_subtraction, void_subtraction);
+};
+static_assert(check_no_iter_
diff erence_t<void_subtraction>());
+
+int main(int, char**) { return 0; }

diff  --git a/libcxx/test/std/iterators/iterator.requirements/iterator.assoc.types/readable.traits/iter_value_t.pass.cpp b/libcxx/test/std/iterators/iterator.requirements/iterator.assoc.types/readable.traits/iter_value_t.pass.cpp
new file mode 100644
index 000000000000..8b459b22769e
--- /dev/null
+++ b/libcxx/test/std/iterators/iterator.requirements/iterator.assoc.types/readable.traits/iter_value_t.pass.cpp
@@ -0,0 +1,75 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+
+// template<class T>
+// using iter_value_t;
+
+#include <iterator>
+
+#include <concepts>
+#include <memory>
+#include <vector>
+
+template <class T, class Expected>
+[[nodiscard]] constexpr bool check_iter_value_t() {
+  constexpr bool result = std::same_as<std::iter_value_t<T>, Expected>;
+  static_assert(std::same_as<std::iter_value_t<T const>, Expected> == result);
+  static_assert(std::same_as<std::iter_value_t<T volatile>, Expected> == result);
+  static_assert(std::same_as<std::iter_value_t<T const volatile>, Expected> == result);
+  static_assert(std::same_as<std::iter_value_t<T const&>, Expected> == result);
+  static_assert(std::same_as<std::iter_value_t<T volatile&>, Expected> == result);
+  static_assert(std::same_as<std::iter_value_t<T const volatile&>, Expected> == result);
+  static_assert(std::same_as<std::iter_value_t<T const&&>, Expected> == result);
+  static_assert(std::same_as<std::iter_value_t<T volatile&&>, Expected> == result);
+  static_assert(std::same_as<std::iter_value_t<T const volatile&&>, Expected> == result);
+
+  return result;
+}
+
+static_assert(check_iter_value_t<int*, int>());
+static_assert(check_iter_value_t<int[], int>());
+static_assert(check_iter_value_t<int[10], int>());
+static_assert(check_iter_value_t<std::vector<int>::iterator, std::vector<int>::iterator::value_type>());
+static_assert(check_iter_value_t<std::shared_ptr<int>, std::shared_ptr<int>::element_type>());
+
+struct both_members {
+  using value_type = double;
+  using element_type = double;
+};
+static_assert(check_iter_value_t<both_members, double>());
+
+// clang-format off
+template <class T>
+requires requires { typename std::iter_value_t<T>; }
+[[nodiscard]] constexpr bool check_no_iter_value_t() {
+  return false;
+}
+// clang-format on
+
+template <class T>
+[[nodiscard]] constexpr bool check_no_iter_value_t() {
+  return true;
+}
+
+static_assert(check_no_iter_value_t<void>());
+static_assert(check_no_iter_value_t<double>());
+
+struct S {};
+static_assert(check_no_iter_value_t<S>());
+
+struct 
diff erent_value_element_members {
+  using value_type = int;
+  using element_type = long;
+};
+static_assert(check_no_iter_value_t<
diff erent_value_element_members>());
+
+int main(int, char**) { return 0; }


        


More information about the libcxx-commits mailing list