diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt --- a/libcxx/include/CMakeLists.txt +++ b/libcxx/include/CMakeLists.txt @@ -11,6 +11,9 @@ __functional_base __functional_base_03 __hash_table + __iterator/concepts.h + __iterator/incrementable_traits.h + __iterator/readable_traits.h __libcpp_version __locale __memory/addressof.h diff --git a/libcxx/include/__iterator/concepts.h b/libcxx/include/__iterator/concepts.h new file mode 100644 --- /dev/null +++ b/libcxx/include/__iterator/concepts.h @@ -0,0 +1,46 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ITERATOR_CONCEPTS_H +#define _LIBCPP___ITERATOR_CONCEPTS_H + +#include <__config> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if !defined(_LIBCPP_HAS_NO_RANGES) + +template +using __with_reference = _Tp&; + +template +concept __referenceable = requires { + typename __with_reference<_Tp>; +}; + +template +concept __dereferenceable = requires(_Tp& __t) { + { *__t } -> __referenceable; // not required to be equality-preserving +}; + +#endif // !defined(_LIBCPP_HAS_NO_RANGES) + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___ITERATOR_CONCEPTS_H diff --git a/libcxx/include/__iterator/incrementable_traits.h b/libcxx/include/__iterator/incrementable_traits.h new file mode 100644 --- /dev/null +++ b/libcxx/include/__iterator/incrementable_traits.h @@ -0,0 +1,65 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ITERATOR_INCREMENTABLE_TRAITS_H +#define _LIBCPP___ITERATOR_INCREMENTABLE_TRAITS_H + +#include <__config> +#include <__iterator/concepts.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if !defined(_LIBCPP_HAS_NO_RANGES) + +// [incrementable.traits] +template struct incrementable_traits {}; + +template +requires is_object_v<_Tp> +struct incrementable_traits<_Tp*> { + using difference_type = ptrdiff_t; +}; + +template +struct incrementable_traits : incrementable_traits<_Ip> {}; + +template +concept __has_member_difference_type = requires { typename _Tp::difference_type; }; + +template<__has_member_difference_type _Tp> +struct incrementable_traits<_Tp> { + using difference_type = typename _Tp::difference_type; +}; + +template +concept __has_integral_minus = + requires(const _Tp& __x, const _Tp& __y) { + { __x - __y } -> integral; + }; + +template<__has_integral_minus _Tp> +requires (!__has_member_difference_type<_Tp>) +struct incrementable_traits<_Tp> { + using difference_type = make_signed_t() - declval<_Tp>())>; +}; + +#endif // !defined(_LIBCPP_HAS_NO_RANGES) + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___ITERATOR_INCREMENTABLE_TRAITS_H diff --git a/libcxx/include/__iterator/readable_traits.h b/libcxx/include/__iterator/readable_traits.h new file mode 100644 --- /dev/null +++ b/libcxx/include/__iterator/readable_traits.h @@ -0,0 +1,79 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ITERATOR_READABLE_TRAITS_H +#define _LIBCPP___ITERATOR_READABLE_TRAITS_H + +#include <__config> +#include <__iterator/concepts.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if !defined(_LIBCPP_HAS_NO_RANGES) + +// [readable.traits] +template struct __cond_value_type {}; + +template +requires is_object_v<_Tp> +struct __cond_value_type<_Tp> { using value_type = remove_cv_t<_Tp>; }; + +template +concept __has_member_value_type = requires { typename _Tp::value_type; }; + +template +concept __has_member_element_type = requires { typename _Tp::element_type; }; + +template struct indirectly_readable_traits {}; + +template +requires is_array_v<_Ip> +struct indirectly_readable_traits<_Ip> { + using value_type = remove_cv_t>; +}; + +template +struct indirectly_readable_traits : indirectly_readable_traits<_Ip> {}; + +template +struct indirectly_readable_traits<_Tp*> : __cond_value_type<_Tp> {}; + +template<__has_member_value_type _Tp> +struct indirectly_readable_traits<_Tp> + : __cond_value_type {}; + +template<__has_member_element_type _Tp> +struct indirectly_readable_traits<_Tp> + : __cond_value_type {}; + +// Pre-emptively applies LWG3541 +template<__has_member_value_type _Tp> +requires __has_member_element_type<_Tp> +struct indirectly_readable_traits<_Tp> {}; +template<__has_member_value_type _Tp> +requires __has_member_element_type<_Tp> && + same_as, + remove_cv_t> +struct indirectly_readable_traits<_Tp> + : __cond_value_type {}; + +#endif // !defined(_LIBCPP_HAS_NO_RANGES) + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___ITERATOR_READABLE_TRAITS_H diff --git a/libcxx/include/concepts b/libcxx/include/concepts --- a/libcxx/include/concepts +++ b/libcxx/include/concepts @@ -439,6 +439,7 @@ // [concept.strictweakorder] template concept strict_weak_order = relation<_Rp, _Tp, _Up>; + #endif //_LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_CONCEPTS) _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/iterator b/libcxx/include/iterator --- a/libcxx/include/iterator +++ b/libcxx/include/iterator @@ -429,6 +429,8 @@ #include #include #include +#include <__iterator/incrementable_traits.h> +#include <__iterator/readable_traits.h> #include <__memory/addressof.h> #include <__memory/pointer_traits.h> #include @@ -443,99 +445,6 @@ #if !defined(_LIBCPP_HAS_NO_RANGES) -template -using __with_reference = _Tp&; - -template -concept __referenceable = requires { - typename __with_reference<_Tp>; -}; - -template -concept __dereferenceable = requires(_Tp& __t) { - { *__t } -> __referenceable; // not required to be equality-preserving -}; - -// [incrementable.traits] -template struct incrementable_traits {}; - -template -requires is_object_v<_Tp> -struct incrementable_traits<_Tp*> { - using difference_type = ptrdiff_t; -}; - -template -struct incrementable_traits : incrementable_traits<_Ip> {}; - -template -concept __has_member_difference_type = requires { typename _Tp::difference_type; }; - -template<__has_member_difference_type _Tp> -struct incrementable_traits<_Tp> { - using difference_type = typename _Tp::difference_type; -}; - -template -concept __has_integral_minus = - requires(const _Tp& __x, const _Tp& __y) { - { __x - __y } -> integral; - }; - -template<__has_integral_minus _Tp> -requires (!__has_member_difference_type<_Tp>) -struct incrementable_traits<_Tp> { - using difference_type = make_signed_t() - declval<_Tp>())>; -}; - -// TODO(cjdb): add iter_difference_t once iterator_traits is cleaned up. - -// [readable.traits] -template struct __cond_value_type {}; - -template -requires is_object_v<_Tp> -struct __cond_value_type<_Tp> { using value_type = remove_cv_t<_Tp>; }; - -template -concept __has_member_value_type = requires { typename _Tp::value_type; }; - -template -concept __has_member_element_type = requires { typename _Tp::element_type; }; - -template struct indirectly_readable_traits {}; - -template -requires is_array_v<_Ip> -struct indirectly_readable_traits<_Ip> { - using value_type = remove_cv_t>; -}; - -template -struct indirectly_readable_traits : indirectly_readable_traits<_Ip> {}; - -template -struct indirectly_readable_traits<_Tp*> : __cond_value_type<_Tp> {}; - -template<__has_member_value_type _Tp> -struct indirectly_readable_traits<_Tp> - : __cond_value_type {}; - -template<__has_member_element_type _Tp> -struct indirectly_readable_traits<_Tp> - : __cond_value_type {}; - -// Pre-emptively applies LWG3541 -template<__has_member_value_type _Tp> -requires __has_member_element_type<_Tp> -struct indirectly_readable_traits<_Tp> {}; -template<__has_member_value_type _Tp> -requires __has_member_element_type<_Tp> && - same_as, - remove_cv_t> -struct indirectly_readable_traits<_Tp> - : __cond_value_type {}; - // [iterator.traits] template<__dereferenceable _Tp> using iter_reference_t = decltype(*declval<_Tp&>());