176d0caaeSpatrick //===----------------------------------------------------------------------===// 276d0caaeSpatrick // 376d0caaeSpatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 476d0caaeSpatrick // See https://llvm.org/LICENSE.txt for license information. 576d0caaeSpatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 676d0caaeSpatrick // 776d0caaeSpatrick //===----------------------------------------------------------------------===// 876d0caaeSpatrick 976d0caaeSpatrick #ifndef _LIBCPP___ALGORITHM_UNWRAP_ITER_H 1076d0caaeSpatrick #define _LIBCPP___ALGORITHM_UNWRAP_ITER_H 1176d0caaeSpatrick 1276d0caaeSpatrick #include <__config> 13*4bdff4beSrobert #include <__iterator/iterator_traits.h> 1476d0caaeSpatrick #include <__memory/pointer_traits.h> 15*4bdff4beSrobert #include <__type_traits/enable_if.h> 16*4bdff4beSrobert #include <__type_traits/is_copy_constructible.h> 17*4bdff4beSrobert #include <__utility/declval.h> 18*4bdff4beSrobert #include <__utility/move.h> 1976d0caaeSpatrick 2076d0caaeSpatrick #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 2176d0caaeSpatrick # pragma GCC system_header 2276d0caaeSpatrick #endif 2376d0caaeSpatrick 2476d0caaeSpatrick _LIBCPP_BEGIN_NAMESPACE_STD 2576d0caaeSpatrick 26*4bdff4beSrobert // TODO: Change the name of __unwrap_iter_impl to something more appropriate 27*4bdff4beSrobert // The job of __unwrap_iter is to remove iterator wrappers (like reverse_iterator or __wrap_iter), 28*4bdff4beSrobert // to reduce the number of template instantiations and to enable pointer-based optimizations e.g. in std::copy. 2976d0caaeSpatrick // In debug mode, we don't do this. 3076d0caaeSpatrick // 3176d0caaeSpatrick // Some algorithms (e.g. std::copy, but not std::sort) need to convert an 32*4bdff4beSrobert // "unwrapped" result back into the original iterator type. Doing that is the job of __rewrap_iter. 3376d0caaeSpatrick 34*4bdff4beSrobert // Default case - we can't unwrap anything 3576d0caaeSpatrick template <class _Iter, bool = __is_cpp17_contiguous_iterator<_Iter>::value> 3676d0caaeSpatrick struct __unwrap_iter_impl { __rewrap__unwrap_iter_impl37*4bdff4beSrobert static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Iter __rewrap(_Iter, _Iter __iter) { return __iter; } __unwrap__unwrap_iter_impl38*4bdff4beSrobert static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Iter __unwrap(_Iter __i) _NOEXCEPT { return __i; } 3976d0caaeSpatrick }; 4076d0caaeSpatrick 41*4bdff4beSrobert #ifndef _LIBCPP_ENABLE_DEBUG_MODE 4276d0caaeSpatrick 43*4bdff4beSrobert // It's a contiguous iterator, so we can use a raw pointer instead 4476d0caaeSpatrick template <class _Iter> 4576d0caaeSpatrick struct __unwrap_iter_impl<_Iter, true> { 46*4bdff4beSrobert using _ToAddressT = decltype(std::__to_address(std::declval<_Iter>())); 47*4bdff4beSrobert 48*4bdff4beSrobert static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Iter __rewrap(_Iter __orig_iter, _ToAddressT __unwrapped_iter) { 49*4bdff4beSrobert return __orig_iter + (__unwrapped_iter - std::__to_address(__orig_iter)); 50*4bdff4beSrobert } 51*4bdff4beSrobert 52*4bdff4beSrobert static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _ToAddressT __unwrap(_Iter __i) _NOEXCEPT { 53*4bdff4beSrobert return std::__to_address(__i); 5476d0caaeSpatrick } 5576d0caaeSpatrick }; 5676d0caaeSpatrick 57*4bdff4beSrobert #endif // !_LIBCPP_ENABLE_DEBUG_MODE 5876d0caaeSpatrick 59*4bdff4beSrobert template<class _Iter, 60*4bdff4beSrobert class _Impl = __unwrap_iter_impl<_Iter>, 61*4bdff4beSrobert __enable_if_t<is_copy_constructible<_Iter>::value, int> = 0> 62*4bdff4beSrobert inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 63*4bdff4beSrobert decltype(_Impl::__unwrap(std::declval<_Iter>())) __unwrap_iter(_Iter __i) _NOEXCEPT { 64*4bdff4beSrobert return _Impl::__unwrap(__i); 6576d0caaeSpatrick } 6676d0caaeSpatrick 67*4bdff4beSrobert template <class _OrigIter, class _Iter, class _Impl = __unwrap_iter_impl<_OrigIter> > 68*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _OrigIter __rewrap_iter(_OrigIter __orig_iter, _Iter __iter) _NOEXCEPT { 69*4bdff4beSrobert return _Impl::__rewrap(std::move(__orig_iter), std::move(__iter)); 7076d0caaeSpatrick } 7176d0caaeSpatrick 7276d0caaeSpatrick _LIBCPP_END_NAMESPACE_STD 7376d0caaeSpatrick 7476d0caaeSpatrick #endif // _LIBCPP___ALGORITHM_UNWRAP_ITER_H 75