Home | History | Annotate | Line # | Download | only in __iterator
      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_READABLE_TRAITS_H
     11 #define _LIBCPP___ITERATOR_READABLE_TRAITS_H
     12 
     13 #include <__config>
     14 #include <concepts>
     15 #include <type_traits>
     16 
     17 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
     18 #pragma GCC system_header
     19 #endif
     20 
     21 _LIBCPP_PUSH_MACROS
     22 #include <__undef_macros>
     23 
     24 _LIBCPP_BEGIN_NAMESPACE_STD
     25 
     26 #if !defined(_LIBCPP_HAS_NO_RANGES)
     27 
     28 // [readable.traits]
     29 template<class> struct __cond_value_type {};
     30 
     31 template<class _Tp>
     32 requires is_object_v<_Tp>
     33 struct __cond_value_type<_Tp> { using value_type = remove_cv_t<_Tp>; };
     34 
     35 template<class _Tp>
     36 concept __has_member_value_type = requires { typename _Tp::value_type; };
     37 
     38 template<class _Tp>
     39 concept __has_member_element_type = requires { typename _Tp::element_type; };
     40 
     41 template<class> struct indirectly_readable_traits {};
     42 
     43 template<class _Ip>
     44 requires is_array_v<_Ip>
     45 struct indirectly_readable_traits<_Ip> {
     46   using value_type = remove_cv_t<remove_extent_t<_Ip>>;
     47 };
     48 
     49 template<class _Ip>
     50 struct indirectly_readable_traits<const _Ip> : indirectly_readable_traits<_Ip> {};
     51 
     52 template<class _Tp>
     53 struct indirectly_readable_traits<_Tp*> : __cond_value_type<_Tp> {};
     54 
     55 template<__has_member_value_type _Tp>
     56 struct indirectly_readable_traits<_Tp>
     57   : __cond_value_type<typename _Tp::value_type> {};
     58 
     59 template<__has_member_element_type _Tp>
     60 struct indirectly_readable_traits<_Tp>
     61   : __cond_value_type<typename _Tp::element_type> {};
     62 
     63 // Pre-emptively applies LWG3541
     64 template<__has_member_value_type _Tp>
     65 requires __has_member_element_type<_Tp>
     66 struct indirectly_readable_traits<_Tp> {};
     67 template<__has_member_value_type _Tp>
     68 requires __has_member_element_type<_Tp> &&
     69          same_as<remove_cv_t<typename _Tp::element_type>,
     70                  remove_cv_t<typename _Tp::value_type>>
     71 struct indirectly_readable_traits<_Tp>
     72   : __cond_value_type<typename _Tp::value_type> {};
     73 
     74 template <class>
     75 struct iterator_traits;
     76 
     77 // Let `RI` be `remove_cvref_t<I>`. The type `iter_value_t<I>` denotes
     78 // `indirectly_readable_traits<RI>::value_type` if `iterator_traits<RI>` names a specialization
     79 // generated from the primary template, and `iterator_traits<RI>::value_type` otherwise.
     80 template <class _Ip>
     81 using iter_value_t = typename conditional_t<__is_primary_template<iterator_traits<remove_cvref_t<_Ip> > >::value,
     82                                             indirectly_readable_traits<remove_cvref_t<_Ip> >,
     83                                             iterator_traits<remove_cvref_t<_Ip> > >::value_type;
     84 
     85 #endif // !defined(_LIBCPP_HAS_NO_RANGES)
     86 
     87 _LIBCPP_END_NAMESPACE_STD
     88 
     89 _LIBCPP_POP_MACROS
     90 
     91 #endif // _LIBCPP___ITERATOR_READABLE_TRAITS_H
     92