diff --git a/libcxx/docs/OneRangesProposalStatus.csv b/libcxx/docs/OneRangesProposalStatus.csv --- a/libcxx/docs/OneRangesProposalStatus.csv +++ b/libcxx/docs/OneRangesProposalStatus.csv @@ -3,13 +3,13 @@ [tuple.helper],Update includes.,,,, [function.objects],"Comparison functions: equal_to, less, etc.",[concepts],Zoe Carver,`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 `_, -[iterator.traits],Mainly updates to iterator_traits.,"[readable.traits]: indirectly_readable_traits, [concepts]",Christopher Di Bella,"`D99854 `_, `D99855 `_", -[readable.traits]: iter_value_t,Finish implementing readable.traits.,"[readable.traits]: indirectly_readable_traits, [concepts], [iterator.traits]",Christopher Di Bella,`D99863 `_, +[readable.traits]: indirectly_readable_traits,indirectly_readable_traits only. ,[concepts],Christopher Di Bella,`D99461 `_,✅ +[iterator.traits],Mainly updates to iterator_traits.,"[readable.traits]: indirectly_readable_traits, [concepts]",Christopher Di Bella,"`D99854 `_, `D99855 `_",✅ +[readable.traits]: iter_value_t,Finish implementing readable.traits.,"[readable.traits]: indirectly_readable_traits, [concepts], [iterator.traits]",Christopher Di Bella,`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 `_, `D99863 `_",1/2 +[incrementable.traits],,[concepts],Christopher Di Bella,"`D99141 `_, `D99863 `_",✅ [iterator.cust.move],Implement iter_move.,,Christopher Di Bella,`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 `_ diff --git a/libcxx/include/__iterator/incrementable_traits.h b/libcxx/include/__iterator/incrementable_traits.h --- 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 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header @@ -56,6 +57,17 @@ using difference_type = make_signed_t() - declval<_Tp>())>; }; +template +struct iterator_traits; + +// Let `RI` be `remove_­cvref_­t`. The type `iter_­difference_­t` denotes +// `incrementable_­traits::difference_­type` if `iterator_­traits` names a specialization +// generated from the primary template, and `iterator_­traits::difference_­type` otherwise. +template +using iter_difference_t = typename conditional_t<__is_primary_template > >::value, + incrementable_traits >, + iterator_traits > >::difference_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 --- a/libcxx/include/__iterator/readable_traits.h +++ b/libcxx/include/__iterator/readable_traits.h @@ -70,6 +70,17 @@ struct indirectly_readable_traits<_Tp> : __cond_value_type {}; +template +struct iterator_traits; + +// Let `RI` be `remove_­cvref_­t`. The type `iter_­value_­t` denotes +// `indirectly_­readable_­traits::value_­type` if `iterator_­traits` names a specialization +// generated from the primary template, and `iterator_­traits::value_­type` otherwise. +template +using iter_value_t = typename conditional_t<__is_primary_template > >::value, + indirectly_readable_traits >, + iterator_traits > >::value_type; + #endif // !defined(_LIBCPP_HAS_NO_RANGES) _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/iterator b/libcxx/include/iterator --- a/libcxx/include/iterator +++ b/libcxx/include/iterator @@ -18,7 +18,12 @@ namespace std { template struct incrementable_traits; // since C++20 +template + using iter_difference_t = see below; // since C++20 + template struct indirectly_readable_traits; // since C++20 +template + using iter_value_t = see below; // since C++20 template struct iterator_traits; diff --git a/libcxx/test/std/iterators/iterator.requirements/iterator.assoc.types/incrementable.traits/iter_difference_t.pass.cpp b/libcxx/test/std/iterators/iterator.requirements/iterator.assoc.types/incrementable.traits/iter_difference_t.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/iterators/iterator.requirements/iterator.assoc.types/incrementable.traits/iter_difference_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 +// using iter_difference_t; + +#include + +#include +#include + +template +[[nodiscard]] constexpr bool check_iter_difference_t() { + constexpr bool result = std::same_as, Expected>; + static_assert(std::same_as, Expected> == result); + static_assert(std::same_as, Expected> == result); + static_assert(std::same_as, Expected> == result); + static_assert(std::same_as, Expected> == result); + static_assert(std::same_as, Expected> == result); + static_assert(std::same_as, Expected> == result); + static_assert(std::same_as, Expected> == result); + static_assert(std::same_as, Expected> == result); + static_assert(std::same_as, Expected> == result); + + return result; +} + +static_assert(check_iter_difference_t()); +static_assert(check_iter_difference_t()); +static_assert(check_iter_difference_t::iterator, std::vector::iterator::difference_type>()); + +struct int_subtraction { + friend int operator-(int_subtraction, int_subtraction) noexcept; +}; +static_assert(check_iter_difference_t()); + +// clang-format off +template +requires requires { typename std::iter_difference_t; } +[[nodiscard]] constexpr bool check_no_iter_difference_t() { + return false; +} +// clang-format on + +template +[[nodiscard]] constexpr bool check_no_iter_difference_t() { + return true; +} + +static_assert(check_no_iter_difference_t()); +static_assert(check_no_iter_difference_t()); + +struct S {}; +static_assert(check_no_iter_difference_t()); + +struct void_subtraction { + friend void operator-(void_subtraction, void_subtraction); +}; +static_assert(check_no_iter_difference_t()); + +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 --- /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 +// using iter_value_t; + +#include + +#include +#include +#include + +template +[[nodiscard]] constexpr bool check_iter_value_t() { + constexpr bool result = std::same_as, Expected>; + static_assert(std::same_as, Expected> == result); + static_assert(std::same_as, Expected> == result); + static_assert(std::same_as, Expected> == result); + static_assert(std::same_as, Expected> == result); + static_assert(std::same_as, Expected> == result); + static_assert(std::same_as, Expected> == result); + static_assert(std::same_as, Expected> == result); + static_assert(std::same_as, Expected> == result); + static_assert(std::same_as, Expected> == result); + + return result; +} + +static_assert(check_iter_value_t()); +static_assert(check_iter_value_t()); +static_assert(check_iter_value_t()); +static_assert(check_iter_value_t::iterator, std::vector::iterator::value_type>()); +static_assert(check_iter_value_t, std::shared_ptr::element_type>()); + +struct both_members { + using value_type = double; + using element_type = double; +}; +static_assert(check_iter_value_t()); + +// clang-format off +template +requires requires { typename std::iter_value_t; } +[[nodiscard]] constexpr bool check_no_iter_value_t() { + return false; +} +// clang-format on + +template +[[nodiscard]] constexpr bool check_no_iter_value_t() { + return true; +} + +static_assert(check_no_iter_value_t()); +static_assert(check_no_iter_value_t()); + +struct S {}; +static_assert(check_no_iter_value_t()); + +struct different_value_element_members { + using value_type = int; + using element_type = long; +}; +static_assert(check_no_iter_value_t()); + +int main(int, char**) { return 0; }