[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
This commit is contained in:
Christopher Di Bella
2021-04-20 18:56:08 +00:00
parent 6f4f0afaa8
commit 9816d43cff
6 changed files with 177 additions and 4 deletions

View File

@@ -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>`_
1 Section Description Dependencies Assignee Patch Complete
3 [tuple.helper] Update <tuple> includes.
4 [function.objects] Comparison functions: equal_to, less, etc. [concepts] Zoe Carver `D100429 <https://reviews.llvm.org/D100429>`_
5 [memory.syn] Add specializations for uninitialized_* and destroy_*. [concepts], [readable.traits]: iter_value_t
6 [readable.traits]: indirectly_readable_traits indirectly_readable_traits only. [concepts] Christopher Di Bella `D99461 <https://reviews.llvm.org/D99461>`_
7 [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>`_
8 [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>`_
9 [specialized.algorithms] NOT FINISHED NOT FINISHED
10 [strings] Adds begin/end and updates const_iterator. [iterator.concepts]
11 [views.span] Same as [strings] [iterator.concepts]
12 [incrementable.traits] [concepts] Christopher Di Bella `D99141 <https://reviews.llvm.org/D99141>`_, `D99863 <https://reviews.llvm.org/D99863>`_ 1/2
13 [iterator.cust.move] Implement iter_move. Christopher Di Bella `D99873 <https://reviews.llvm.org/D99873>`_
14 [iterator.cust.swap] Implement iter_swap. [concepts], [readable.traits]: iter_value_t
15 [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>`_ indirectly_wriatable: `D100078 <https://reviews.llvm.org/D100078>`_ weakly_incrementable, incrementable: `D100080 <https://reviews.llvm.org/D100080>`_ input_or_output_iterator, sentinel_for: `D100160 <https://reviews.llvm.org/D100160>`_ input_iterator: `D100271 <https://reviews.llvm.org/D100271>`_ forward_iterator: `D100275 <https://reviews.llvm.org/D100275>`_ bidirectional_iterator: `D100278 <https://reviews.llvm.org/D100278>`_

View File

@@ -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 difference_type = make_signed_t<decltype(declval<_Tp>() - declval<_Tp>())>;
};
template <class>
struct iterator_traits;
// Let `RI` be `remove_­cvref_­t<I>`. The type `iter_­difference_­t<I>` denotes
// `incrementable_­traits<RI>::difference_­type` if `iterator_­traits<RI>` names a specialization
// generated from the primary template, and `iterator_­traits<RI>::difference_­type` otherwise.
template <class _Ip>
using iter_difference_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> > >::difference_type;
#endif // !defined(_LIBCPP_HAS_NO_RANGES)
_LIBCPP_END_NAMESPACE_STD

View File

@@ -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

View File

@@ -18,7 +18,12 @@
namespace std
{
template<class> struct incrementable_traits; // since C++20
template<class T>
using iter_difference_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;

View File

@@ -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_difference_t;
#include <iterator>
#include <concepts>
#include <vector>
template <class T, class Expected>
[[nodiscard]] constexpr bool check_iter_difference_t() {
constexpr bool result = std::same_as<std::iter_difference_t<T>, Expected>;
static_assert(std::same_as<std::iter_difference_t<T const>, Expected> == result);
static_assert(std::same_as<std::iter_difference_t<T volatile>, Expected> == result);
static_assert(std::same_as<std::iter_difference_t<T const volatile>, Expected> == result);
static_assert(std::same_as<std::iter_difference_t<T const&>, Expected> == result);
static_assert(std::same_as<std::iter_difference_t<T volatile&>, Expected> == result);
static_assert(std::same_as<std::iter_difference_t<T const volatile&>, Expected> == result);
static_assert(std::same_as<std::iter_difference_t<T const&&>, Expected> == result);
static_assert(std::same_as<std::iter_difference_t<T volatile&&>, Expected> == result);
static_assert(std::same_as<std::iter_difference_t<T const volatile&&>, Expected> == result);
return result;
}
static_assert(check_iter_difference_t<int, int>());
static_assert(check_iter_difference_t<int*, std::ptrdiff_t>());
static_assert(check_iter_difference_t<std::vector<int>::iterator, std::vector<int>::iterator::difference_type>());
struct int_subtraction {
friend int operator-(int_subtraction, int_subtraction) noexcept;
};
static_assert(check_iter_difference_t<int_subtraction, int>());
// clang-format off
template <class T>
requires requires { typename std::iter_difference_t<T>; }
[[nodiscard]] constexpr bool check_no_iter_difference_t() {
return false;
}
// clang-format on
template <class T>
[[nodiscard]] constexpr bool check_no_iter_difference_t() {
return true;
}
static_assert(check_no_iter_difference_t<void>());
static_assert(check_no_iter_difference_t<double>());
struct S {};
static_assert(check_no_iter_difference_t<S>());
struct void_subtraction {
friend void operator-(void_subtraction, void_subtraction);
};
static_assert(check_no_iter_difference_t<void_subtraction>());
int main(int, char**) { return 0; }

View File

@@ -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 different_value_element_members {
using value_type = int;
using element_type = long;
};
static_assert(check_no_iter_value_t<different_value_element_members>());
int main(int, char**) { return 0; }