xref: /freebsd/contrib/llvm-project/libcxx/include/__iterator/incrementable_traits.h (revision cb14a3fe5122c879eae1fb480ed7ce82a699ddb6)
1fe6060f1SDimitry Andric // -*- C++ -*-
2fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
3fe6060f1SDimitry Andric //
4fe6060f1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5fe6060f1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
6fe6060f1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7fe6060f1SDimitry Andric //
8fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
9fe6060f1SDimitry Andric 
10fe6060f1SDimitry Andric #ifndef _LIBCPP___ITERATOR_INCREMENTABLE_TRAITS_H
11fe6060f1SDimitry Andric #define _LIBCPP___ITERATOR_INCREMENTABLE_TRAITS_H
12fe6060f1SDimitry Andric 
13bdd1243dSDimitry Andric #include <__concepts/arithmetic.h>
14fe6060f1SDimitry Andric #include <__config>
15bdd1243dSDimitry Andric #include <__type_traits/conditional.h>
16bdd1243dSDimitry Andric #include <__type_traits/is_object.h>
17972a253aSDimitry Andric #include <__type_traits/is_primary_template.h>
18bdd1243dSDimitry Andric #include <__type_traits/make_signed.h>
19bdd1243dSDimitry Andric #include <__type_traits/remove_cvref.h>
20bdd1243dSDimitry Andric #include <__utility/declval.h>
2161cfbce3SDimitry Andric #include <cstddef>
22fe6060f1SDimitry Andric 
23fe6060f1SDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
24fe6060f1SDimitry Andric #  pragma GCC system_header
25fe6060f1SDimitry Andric #endif
26fe6060f1SDimitry Andric 
27fe6060f1SDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD
28fe6060f1SDimitry Andric 
2906c3fb27SDimitry Andric #if _LIBCPP_STD_VER >= 20
30fe6060f1SDimitry Andric 
31fe6060f1SDimitry Andric // [incrementable.traits]
32*cb14a3feSDimitry Andric template <class>
33*cb14a3feSDimitry Andric struct incrementable_traits {};
34fe6060f1SDimitry Andric 
35fe6060f1SDimitry Andric template <class _Tp>
36fe6060f1SDimitry Andric   requires is_object_v<_Tp>
37fe6060f1SDimitry Andric struct incrementable_traits<_Tp*> {
38fe6060f1SDimitry Andric   using difference_type = ptrdiff_t;
39fe6060f1SDimitry Andric };
40fe6060f1SDimitry Andric 
41fe6060f1SDimitry Andric template <class _Ip>
42fe6060f1SDimitry Andric struct incrementable_traits<const _Ip> : incrementable_traits<_Ip> {};
43fe6060f1SDimitry Andric 
44fe6060f1SDimitry Andric template <class _Tp>
45fe6060f1SDimitry Andric concept __has_member_difference_type = requires { typename _Tp::difference_type; };
46fe6060f1SDimitry Andric 
47fe6060f1SDimitry Andric template <__has_member_difference_type _Tp>
48fe6060f1SDimitry Andric struct incrementable_traits<_Tp> {
49fe6060f1SDimitry Andric   using difference_type = typename _Tp::difference_type;
50fe6060f1SDimitry Andric };
51fe6060f1SDimitry Andric 
52fe6060f1SDimitry Andric template <class _Tp>
53*cb14a3feSDimitry Andric concept __has_integral_minus = requires(const _Tp& __x, const _Tp& __y) {
54fe6060f1SDimitry Andric   { __x - __y } -> integral;
55fe6060f1SDimitry Andric };
56fe6060f1SDimitry Andric 
57fe6060f1SDimitry Andric template <__has_integral_minus _Tp>
58fe6060f1SDimitry Andric   requires(!__has_member_difference_type<_Tp>)
59fe6060f1SDimitry Andric struct incrementable_traits<_Tp> {
60bdd1243dSDimitry Andric   using difference_type = make_signed_t<decltype(std::declval<_Tp>() - std::declval<_Tp>())>;
61fe6060f1SDimitry Andric };
62fe6060f1SDimitry Andric 
63fe6060f1SDimitry Andric template <class>
64fe6060f1SDimitry Andric struct iterator_traits;
65fe6060f1SDimitry Andric 
66fe6060f1SDimitry Andric // Let `RI` be `remove_cvref_t<I>`. The type `iter_difference_t<I>` denotes
67fe6060f1SDimitry Andric // `incrementable_traits<RI>::difference_type` if `iterator_traits<RI>` names a specialization
68fe6060f1SDimitry Andric // generated from the primary template, and `iterator_traits<RI>::difference_type` otherwise.
69fe6060f1SDimitry Andric template <class _Ip>
70*cb14a3feSDimitry Andric using iter_difference_t =
71*cb14a3feSDimitry Andric     typename conditional_t<__is_primary_template<iterator_traits<remove_cvref_t<_Ip> > >::value,
72fe6060f1SDimitry Andric                            incrementable_traits<remove_cvref_t<_Ip> >,
73fe6060f1SDimitry Andric                            iterator_traits<remove_cvref_t<_Ip> > >::difference_type;
74fe6060f1SDimitry Andric 
7506c3fb27SDimitry Andric #endif // _LIBCPP_STD_VER >= 20
76fe6060f1SDimitry Andric 
77fe6060f1SDimitry Andric _LIBCPP_END_NAMESPACE_STD
78fe6060f1SDimitry Andric 
79fe6060f1SDimitry Andric #endif // _LIBCPP___ITERATOR_INCREMENTABLE_TRAITS_H
80