mirror of
https://github.com/intel/llvm.git
synced 2026-01-16 05:32:28 +08:00
[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:
@@ -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>`_
|
||||
|
||||
|
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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; }
|
||||
@@ -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; }
|
||||
Reference in New Issue
Block a user