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