// -*- 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 // SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES. // //===----------------------------------------------------------------------===// #ifndef _LIBCUDACXX___ITERATOR_INCREMENTABLE_TRAITS_H #define _LIBCUDACXX___ITERATOR_INCREMENTABLE_TRAITS_H #include #if defined(_CCCL_IMPLICIT_SYSTEM_HEADER_GCC) # pragma GCC system_header #elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_CLANG) # pragma clang system_header #elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_MSVC) # pragma system_header #endif // no system header #include #include #include #include #include #include #include #include #include #include #include #include #include _LIBCUDACXX_BEGIN_NAMESPACE_STD #if _CCCL_STD_VER > 2017 // [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>())>; }; template struct _LIBCUDACXX_TEMPLATE_VIS iterator_traits; // Let `RI` be `remove_cvref_t`. The type `iter_difference_t` denotes // `incrementable_traits::difference_type` if `iterator_traits` names a specialization // generated from the primary template, and `iterator_traits::difference_type` otherwise. template using iter_difference_t = typename conditional_t<__is_primary_template>>::value, incrementable_traits>, iterator_traits>>::difference_type; #elif _CCCL_STD_VER > 2014 // [incrementable.traits] template struct incrementable_traits {}; template struct incrementable_traits<_Tp*, enable_if_t<_CCCL_TRAIT(is_object, _Tp)>> { using difference_type = ptrdiff_t; }; template struct incrementable_traits : incrementable_traits<_Ip> {}; template _LIBCUDACXX_INLINE_VAR constexpr bool __has_member_difference_type = false; template _LIBCUDACXX_INLINE_VAR constexpr bool __has_member_difference_type<_Tp, void_t> = true; template _LIBCUDACXX_INLINE_VAR constexpr bool __has_integral_minus = false; // In C++17 we get issues trying to bind void* to a const& so special case it here template _LIBCUDACXX_INLINE_VAR constexpr bool __has_integral_minus<_Tp, enable_if_t>, void_t() - _CUDA_VSTD::declval())>> = integral() - _CUDA_VSTD::declval())>; template struct incrementable_traits< _Tp, enable_if_t>> { using difference_type = typename _Tp::difference_type; }; template struct incrementable_traits<_Tp, enable_if_t && __has_integral_minus<_Tp>>> { using difference_type = make_signed_t() - declval<_Tp>())>; }; template struct _LIBCUDACXX_TEMPLATE_VIS iterator_traits; // Let `RI` be `remove_cvref_t`. The type `iter_difference_t` denotes // `incrementable_traits::difference_type` if `iterator_traits` names a specialization // generated from the primary template, and `iterator_traits::difference_type` otherwise. template using iter_difference_t = typename conditional_t<__is_primary_template>>::value, incrementable_traits>, iterator_traits>>::difference_type; #endif // _CCCL_STD_VER > 2014 _LIBCUDACXX_END_NAMESPACE_STD #endif // _LIBCUDACXX___ITERATOR_INCREMENTABLE_TRAITS_H