[libc++] Rewrite std::to_address to avoid relying on element_type
This is a rough reapplication of the change that fixed std::to_address
to avoid relying on element_type (da456167). It is somewhat different
because the fix to avoid breaking Clang (which caused it to be reverted
in 347f69c55) was a bit more involved.
Differential Revision: https://reviews.llvm.org/D101638
NOKEYCHECK=True
GitOrigin-RevId: fe0e86e6026f79e0b18f877196fbddd1d9e140d8
diff --git a/include/__memory/pointer_traits.h b/include/__memory/pointer_traits.h
index 439c658..6730066 100644
--- a/include/__memory/pointer_traits.h
+++ b/include/__memory/pointer_traits.h
@@ -164,64 +164,46 @@
// to_address
-template <bool _UsePointerTraits> struct __to_address_helper;
-
-template <> struct __to_address_helper<true> {
- template <class _Pointer>
- using __return_type = decltype(pointer_traits<_Pointer>::to_address(_VSTD::declval<const _Pointer&>()));
-
- template <class _Pointer>
- _LIBCPP_CONSTEXPR
- static __return_type<_Pointer>
- __do_it(const _Pointer &__p) _NOEXCEPT { return pointer_traits<_Pointer>::to_address(__p); }
-};
-
-template <class _Pointer, bool _Dummy = true>
-using __choose_to_address = __to_address_helper<_IsValidExpansion<__to_address_helper<_Dummy>::template __return_type, _Pointer>::value>;
+template <class _Pointer, class = void>
+struct __to_address_helper;
template <class _Tp>
-inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
-_Tp*
-__to_address(_Tp* __p) _NOEXCEPT
-{
+_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
+_Tp* __to_address(_Tp* __p) _NOEXCEPT {
static_assert(!is_function<_Tp>::value, "_Tp is a function type");
return __p;
}
-template <class _Pointer>
-inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
-typename __choose_to_address<_Pointer>::template __return_type<_Pointer>
-__to_address(const _Pointer& __p) _NOEXCEPT
-{
- return __choose_to_address<_Pointer>::__do_it(__p);
+// enable_if is needed here to avoid instantiating checks for fancy pointers on raw pointers
+template <class _Pointer, class = _EnableIf<!is_pointer<_Pointer>::value> >
+_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
+typename decay<decltype(__to_address_helper<_Pointer>::__call(declval<const _Pointer&>()))>::type
+__to_address(const _Pointer& __p) _NOEXCEPT {
+ return __to_address_helper<_Pointer>::__call(__p);
}
-template <> struct __to_address_helper<false> {
- template <class _Pointer>
- using __return_type = typename pointer_traits<_Pointer>::element_type*;
-
- template <class _Pointer>
- _LIBCPP_CONSTEXPR
- static __return_type<_Pointer>
- __do_it(const _Pointer &__p) _NOEXCEPT { return _VSTD::__to_address(__p.operator->()); }
+template <class _Pointer, class>
+struct __to_address_helper {
+ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
+ static decltype(_VSTD::__to_address(declval<const _Pointer&>().operator->()))
+ __call(const _Pointer&__p) _NOEXCEPT {
+ return _VSTD::__to_address(__p.operator->());
+ }
};
+template <class _Pointer>
+struct __to_address_helper<_Pointer, decltype((void)pointer_traits<_Pointer>::to_address(declval<const _Pointer&>()))> {
+ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
+ static decltype(pointer_traits<_Pointer>::to_address(declval<const _Pointer&>()))
+ __call(const _Pointer&__p) _NOEXCEPT {
+ return pointer_traits<_Pointer>::to_address(__p);
+ }
+};
#if _LIBCPP_STD_VER > 17
-template <class _Tp>
-inline _LIBCPP_INLINE_VISIBILITY constexpr
-_Tp*
-to_address(_Tp* __p) _NOEXCEPT
-{
- static_assert(!is_function_v<_Tp>, "_Tp is a function type");
- return __p;
-}
-
template <class _Pointer>
inline _LIBCPP_INLINE_VISIBILITY constexpr
-auto
-to_address(const _Pointer& __p) _NOEXCEPT
-{
+auto to_address(const _Pointer& __p) noexcept {
return _VSTD::__to_address(__p);
}
#endif
diff --git a/include/iterator b/include/iterator
index 1d308a2..687c641 100644
--- a/include/iterator
+++ b/include/iterator
@@ -1356,7 +1356,7 @@
_LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this),
"Attempted to dereference a non-dereferenceable iterator");
#endif
- return (pointer)_VSTD::addressof(*__i);
+ return _VSTD::__to_address(__i);
}
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG __wrap_iter& operator++() _NOEXCEPT
{