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_ITER_MOVE_H 11fe6060f1SDimitry Andric #define _LIBCPP___ITERATOR_ITER_MOVE_H 12fe6060f1SDimitry Andric 1381ad6265SDimitry Andric #include <__concepts/class_or_enum.h> 14fe6060f1SDimitry Andric #include <__config> 15fe6060f1SDimitry Andric #include <__iterator/iterator_traits.h> 16bdd1243dSDimitry Andric #include <__type_traits/is_reference.h> 17bdd1243dSDimitry Andric #include <__type_traits/remove_cvref.h> 18bdd1243dSDimitry Andric #include <__utility/declval.h> 19fe6060f1SDimitry Andric #include <__utility/forward.h> 2081ad6265SDimitry Andric #include <__utility/move.h> 21fe6060f1SDimitry Andric 22fe6060f1SDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 23fe6060f1SDimitry Andric # pragma GCC system_header 24fe6060f1SDimitry Andric #endif 25fe6060f1SDimitry Andric 2606c3fb27SDimitry Andric _LIBCPP_PUSH_MACROS 2706c3fb27SDimitry Andric #include <__undef_macros> 2806c3fb27SDimitry Andric 29fe6060f1SDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD 30fe6060f1SDimitry Andric 3106c3fb27SDimitry Andric #if _LIBCPP_STD_VER >= 20 32fe6060f1SDimitry Andric 331fd87a68SDimitry Andric // [iterator.cust.move] 341fd87a68SDimitry Andric 351fd87a68SDimitry Andric namespace ranges { 361fd87a68SDimitry Andric namespace __iter_move { 371fd87a68SDimitry Andric 38*0fca6ea1SDimitry Andric void iter_move() = delete; 39fe6060f1SDimitry Andric 401fd87a68SDimitry Andric template <class _Tp> requires(_Tp && __t)41cb14a3feSDimitry Andricconcept __unqualified_iter_move = __class_or_enum<remove_cvref_t<_Tp>> && requires(_Tp&& __t) { 42bdd1243dSDimitry Andric // NOLINTNEXTLINE(libcpp-robust-against-adl) iter_swap ADL calls should only be made through ranges::iter_swap 4381ad6265SDimitry Andric iter_move(std::forward<_Tp>(__t)); 44fe6060f1SDimitry Andric }; 45fe6060f1SDimitry Andric 4681ad6265SDimitry Andric template <class _Tp> 47cb14a3feSDimitry Andric concept __move_deref = !__unqualified_iter_move<_Tp> && requires(_Tp&& __t) { 4881ad6265SDimitry Andric *__t; 4981ad6265SDimitry Andric requires is_lvalue_reference_v<decltype(*__t)>; 5081ad6265SDimitry Andric }; 5181ad6265SDimitry Andric 5281ad6265SDimitry Andric template <class _Tp> 53cb14a3feSDimitry Andric concept __just_deref = !__unqualified_iter_move<_Tp> && !__move_deref<_Tp> && requires(_Tp&& __t) { 5481ad6265SDimitry Andric *__t; 5581ad6265SDimitry Andric requires(!is_lvalue_reference_v<decltype(*__t)>); 5681ad6265SDimitry Andric }; 5781ad6265SDimitry Andric 5881ad6265SDimitry Andric // [iterator.cust.move] 5981ad6265SDimitry Andric 60fe6060f1SDimitry Andric struct __fn { 61bdd1243dSDimitry Andric // NOLINTBEGIN(libcpp-robust-against-adl) iter_move ADL calls should only be made through ranges::iter_move 62fe6060f1SDimitry Andric template <class _Ip> 6381ad6265SDimitry Andric requires __unqualified_iter_move<_Ip> decltype__fn64fe6060f1SDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator()(_Ip&& __i) const 65cb14a3feSDimitry Andric noexcept(noexcept(iter_move(std::forward<_Ip>(__i)))) { 6681ad6265SDimitry Andric return iter_move(std::forward<_Ip>(__i)); 67fe6060f1SDimitry Andric } 68bdd1243dSDimitry Andric // NOLINTEND(libcpp-robust-against-adl) 69fe6060f1SDimitry Andric 70fe6060f1SDimitry Andric template <class _Ip> 7181ad6265SDimitry Andric requires __move_deref<_Ip> 7281ad6265SDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Ip&& __i) const 73cb14a3feSDimitry Andric noexcept(noexcept(std::move(*std::forward<_Ip>(__i)))) -> decltype(std::move(*std::forward<_Ip>(__i))) { 74cb14a3feSDimitry Andric return std::move(*std::forward<_Ip>(__i)); 75cb14a3feSDimitry Andric } 76fe6060f1SDimitry Andric 7781ad6265SDimitry Andric template <class _Ip> 7881ad6265SDimitry Andric requires __just_deref<_Ip> 7981ad6265SDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Ip&& __i) const 80cb14a3feSDimitry Andric noexcept(noexcept(*std::forward<_Ip>(__i))) -> decltype(*std::forward<_Ip>(__i)) { 81cb14a3feSDimitry Andric return *std::forward<_Ip>(__i); 82cb14a3feSDimitry Andric } 83fe6060f1SDimitry Andric }; 841fd87a68SDimitry Andric } // namespace __iter_move 85fe6060f1SDimitry Andric 861fd87a68SDimitry Andric inline namespace __cpo { 87fe6060f1SDimitry Andric inline constexpr auto iter_move = __iter_move::__fn{}; 881fd87a68SDimitry Andric } // namespace __cpo 891fd87a68SDimitry Andric } // namespace ranges 90fe6060f1SDimitry Andric 91fe6060f1SDimitry Andric template <__dereferenceable _Tp> requires(_Tp & __t)92cb14a3feSDimitry Andric requires requires(_Tp& __t) { 93cb14a3feSDimitry Andric { ranges::iter_move(__t) } -> __can_reference; 94cb14a3feSDimitry Andric } 95bdd1243dSDimitry Andric using iter_rvalue_reference_t = decltype(ranges::iter_move(std::declval<_Tp&>())); 96fe6060f1SDimitry Andric 9706c3fb27SDimitry Andric #endif // _LIBCPP_STD_VER >= 20 98fe6060f1SDimitry Andric 99fe6060f1SDimitry Andric _LIBCPP_END_NAMESPACE_STD 100fe6060f1SDimitry Andric 10106c3fb27SDimitry Andric _LIBCPP_POP_MACROS 10206c3fb27SDimitry Andric 103fe6060f1SDimitry Andric #endif // _LIBCPP___ITERATOR_ITER_MOVE_H 104