Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[libc++][WIP] ADL-proof std::__wrap_iter #107766

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions libcxx/include/__configuration/abi.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,14 @@
// and WCHAR_MAX. This ABI setting determines whether we should instead track whether the fill
// value has been initialized using a separate boolean, which changes the ABI.
# define _LIBCPP_ABI_IOS_ALLOW_ARBITRARY_FILL_VALUE
// Change std::__wrap_iter<T> to not associate the namespaces associated with
// T when unqualified lookup (e.g., with operators) is done. Also make it so
// only std::__wrap_iter<pointer> and std::__wrap_iter<const_pointer> can
// be used together (for comparison, conversion, etc.) instead of with any
// wrapped iterator. So comprison between std::__wrap_iter<fancy_pointer<T>>
// and std::__wrap_iter<T*> will no longer compile even if fancy_pointer<T>
// is comparable with T*.
# define _LIBCPP_ABI_WRAP_ITER_ADL_PROOF
#elif _LIBCPP_ABI_VERSION == 1
# if !(defined(_LIBCPP_OBJECT_FORMAT_COFF) || defined(_LIBCPP_OBJECT_FORMAT_XCOFF))
// Enable compiling copies of now inline methods into the dylib to support
Expand Down
2 changes: 1 addition & 1 deletion libcxx/include/__format/buffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ concept __enable_direct_output =
(same_as<_OutIt, _CharT*>
// TODO(hardening): the following check might not apply to hardened iterators and might need to be wrapped in an
// `#ifdef`.
|| same_as<_OutIt, __wrap_iter<_CharT*>>);
|| same_as<_OutIt, __wrap_mut_iter<_CharT*, const _CharT*>>);

/// Write policy for directly writing to the underlying output.
template <class _OutIt, __fmt_char_type _CharT>
Expand Down
10 changes: 10 additions & 0 deletions libcxx/include/__iterator/iterator_traits.h
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,14 @@ template <class _Tp>
struct __libcpp_is_contiguous_iterator
: _Or< __has_iterator_category_convertible_to<_Tp, contiguous_iterator_tag>,
__has_iterator_concept_convertible_to<_Tp, contiguous_iterator_tag> > {};
#elif defined(_LIBCPP_ABI_WRAP_ITER_ADL_PROOF)
template <class _It, class = void>
struct __is_contiguous_wrap_iter : false_type {};
template <class _It>
struct __is_contiguous_wrap_iter<_It, __void_t<typename _Tp::__is_wrap_iter> > : true_type {};

template <class _Tp>
struct __libcpp_is_contiguous_iterator : __is_contiguous_wrap_iter<_Tp> {};
#else
template <class _Tp>
struct __libcpp_is_contiguous_iterator : false_type {};
Expand All @@ -462,8 +470,10 @@ struct __libcpp_is_contiguous_iterator : false_type {};
template <class _Up>
struct __libcpp_is_contiguous_iterator<_Up*> : true_type {};

#ifndef _LIBCPP_ABI_WRAP_ITER_ADL_PROOF
template <class _Iter>
class __wrap_iter;
#endif

template <class _Tp>
using __has_exactly_input_iterator_category =
Expand Down
223 changes: 137 additions & 86 deletions libcxx/include/__iterator/wrap_iter.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,11 @@
#include <__iterator/iterator_traits.h>
#include <__memory/addressof.h>
#include <__memory/pointer_traits.h>
#include <__type_traits/conditional.h>
#include <__type_traits/enable_if.h>
#include <__type_traits/integral_constant.h>
#include <__type_traits/is_convertible.h>
#include <__type_traits/void_t.h>
#include <cstddef>

#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
Expand All @@ -27,15 +29,25 @@

_LIBCPP_BEGIN_NAMESPACE_STD

#ifdef _LIBCPP_ABI_WRAP_ITER_ADL_PROOF
template <class _MutableIter, class _ConstIter>
struct __wrap_iter_impl {
template <bool _IsConst>
#else
template <class _Iter>
class __wrap_iter {
public:
typedef _Iter iterator_type;
typedef typename iterator_traits<iterator_type>::value_type value_type;
typedef typename iterator_traits<iterator_type>::difference_type difference_type;
typedef typename iterator_traits<iterator_type>::pointer pointer;
typedef typename iterator_traits<iterator_type>::reference reference;
typedef typename iterator_traits<iterator_type>::iterator_category iterator_category;
#endif
class __wrap_iter {

public:
#ifdef _LIBCPP_ABI_WRAP_ITER_ADL_PROOF
using _Iter = __conditional_t<_IsConst, _ConstIter, _MutableIter>;
#endif
typedef _Iter iterator_type;
typedef typename iterator_traits<iterator_type>::value_type value_type;
typedef typename iterator_traits<iterator_type>::difference_type difference_type;
typedef typename iterator_traits<iterator_type>::pointer pointer;
typedef typename iterator_traits<iterator_type>::reference reference;
typedef typename iterator_traits<iterator_type>::iterator_category iterator_category;
#if _LIBCPP_STD_VER >= 20
typedef contiguous_iterator_tag iterator_concept;
#endif
Expand All @@ -45,9 +57,15 @@ class __wrap_iter {

public:
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 __wrap_iter() _NOEXCEPT : __i_() {}
#ifdef _LIBCPP_ABI_WRAP_ITER_ADL_PROOF
template <bool _B, __enable_if_t<!_B, int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 __wrap_iter(const __wrap_iter<_B>& __u) _NOEXCEPT
: __i_(__u.base()) {}
#else
template <class _Up, __enable_if_t<is_convertible<_Up, iterator_type>::value, int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 __wrap_iter(const __wrap_iter<_Up>& __u) _NOEXCEPT
: __i_(__u.base()) {}
#endif
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 reference operator*() const _NOEXCEPT { return *__i_; }
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pointer operator->() const _NOEXCEPT {
return std::__to_address(__i_);
Expand Down Expand Up @@ -96,7 +114,13 @@ class __wrap_iter {
private:
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit __wrap_iter(iterator_type __x) _NOEXCEPT : __i_(__x) {}

#ifdef _LIBCPP_ABI_WRAP_ITER_ADL_PROOF
using __is_wrap_iter = void;

template <bool _OtherConst>
#else
template <class _Up>
#endif
friend class __wrap_iter;
template <class _CharT, class _Traits, class _Alloc>
friend class basic_string;
Expand All @@ -108,85 +132,99 @@ class __wrap_iter {
friend class _LIBCPP_TEMPLATE_VIS span;
template <class _Tp, size_t _Size>
friend struct array;
};
};

#ifdef _LIBCPP_ABI_WRAP_ITER_ADL_PROOF
# define _LIBCPP_WRAP_ITER_SINGLE_TEMPLATE_HEAD \
template <bool _Iter1> \
friend
# define _LIBCPP_WRAP_ITER_PAIR_TEMPLATE_HEAD \
template <bool _Iter1, bool _Iter2> \
friend
#else
# define _LIBCPP_WRAP_ITER_SINGLE_TEMPLATE_HEAD template <class _Iter1>
# define _LIBCPP_WRAP_ITER_PAIR_TEMPLATE_HEAD template <class _Iter1, class _Iter2>
#endif

template <class _Iter1>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool
operator==(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter1>& __y) _NOEXCEPT {
return __x.base() == __y.base();
}
_LIBCPP_WRAP_ITER_SINGLE_TEMPLATE_HEAD
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool
operator==(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter1>& __y) _NOEXCEPT {
return __x.base() == __y.base();
}

template <class _Iter1, class _Iter2>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool
operator==(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT {
return __x.base() == __y.base();
}
_LIBCPP_WRAP_ITER_PAIR_TEMPLATE_HEAD
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool
operator==(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT {
return __x.base() == __y.base();
}

template <class _Iter1>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 bool
operator<(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter1>& __y) _NOEXCEPT {
return __x.base() < __y.base();
}
_LIBCPP_WRAP_ITER_SINGLE_TEMPLATE_HEAD
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 bool
operator<(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter1>& __y) _NOEXCEPT {
return __x.base() < __y.base();
}

template <class _Iter1, class _Iter2>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 bool
operator<(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT {
return __x.base() < __y.base();
}
_LIBCPP_WRAP_ITER_PAIR_TEMPLATE_HEAD
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 bool
operator<(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT {
return __x.base() < __y.base();
}

#if _LIBCPP_STD_VER <= 17
template <class _Iter1>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool
operator!=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter1>& __y) _NOEXCEPT {
return !(__x == __y);
}
_LIBCPP_WRAP_ITER_SINGLE_TEMPLATE_HEAD
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool
operator!=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter1>& __y) _NOEXCEPT {
return !(__x == __y);
}

template <class _Iter1, class _Iter2>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool
operator!=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT {
return !(__x == __y);
}
template <class _Iter1>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool
operator>(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter1>& __y) _NOEXCEPT {
return __y < __x;
}
_LIBCPP_WRAP_ITER_PAIR_TEMPLATE_HEAD
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool
operator!=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT {
return !(__x == __y);
}
_LIBCPP_WRAP_ITER_SINGLE_TEMPLATE_HEAD
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool
operator>(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter1>& __y) _NOEXCEPT {
return __y < __x;
}

template <class _Iter1, class _Iter2>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool
operator>(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT {
return __y < __x;
}
_LIBCPP_WRAP_ITER_PAIR_TEMPLATE_HEAD
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool
operator>(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT {
return __y < __x;
}

template <class _Iter1>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool
operator>=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter1>& __y) _NOEXCEPT {
return !(__x < __y);
}
_LIBCPP_WRAP_ITER_SINGLE_TEMPLATE_HEAD
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool
operator>=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter1>& __y) _NOEXCEPT {
return !(__x < __y);
}

template <class _Iter1, class _Iter2>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool
operator>=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT {
return !(__x < __y);
}
_LIBCPP_WRAP_ITER_PAIR_TEMPLATE_HEAD
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool
operator>=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT {
return !(__x < __y);
}

template <class _Iter1>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool
operator<=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter1>& __y) _NOEXCEPT {
return !(__y < __x);
}
_LIBCPP_WRAP_ITER_SINGLE_TEMPLATE_HEAD
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool
operator<=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter1>& __y) _NOEXCEPT {
return !(__y < __x);
}

template <class _Iter1, class _Iter2>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool
operator<=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT {
return !(__y < __x);
}
_LIBCPP_WRAP_ITER_PAIR_TEMPLATE_HEAD
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool
operator<=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT {
return !(__y < __x);
}

#else
template <class _Iter1, class _Iter2>
_LIBCPP_WRAP_ITER_PAIR_TEMPLATE_HEAD
_LIBCPP_HIDE_FROM_ABI constexpr strong_ordering
operator<=>(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) noexcept {
if constexpr (three_way_comparable_with<_Iter1, _Iter2, strong_ordering>) {
if constexpr (three_way_comparable_with<typename __wrap_iter<_Iter1>::iterator_type,
typename __wrap_iter<_Iter2>::iterator_type,
strong_ordering>) {
return __x.base() <=> __y.base();
} else {
if (__x.base() < __y.base())
Expand All @@ -200,31 +238,38 @@ operator<=>(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) noex
}
#endif // _LIBCPP_STD_VER >= 20

template <class _Iter1, class _Iter2>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14
_LIBCPP_WRAP_ITER_PAIR_TEMPLATE_HEAD
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14
#ifndef _LIBCPP_CXX03_LANG
auto
operator-(const __wrap_iter<_Iter1>& __x,
const __wrap_iter<_Iter2>& __y) _NOEXCEPT->decltype(__x.base() - __y.base())
auto
operator-(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT->decltype(__x.base() - __y.base())
#else
typename __wrap_iter<_Iter1>::difference_type
operator-(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT
#endif // C++03
{
{
return __x.base() - __y.base();
}
}

template <class _Iter1>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 __wrap_iter<_Iter1>
operator+(typename __wrap_iter<_Iter1>::difference_type __n, __wrap_iter<_Iter1> __x) _NOEXCEPT {
__x += __n;
return __x;
}
_LIBCPP_WRAP_ITER_SINGLE_TEMPLATE_HEAD
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 __wrap_iter<_Iter1>
operator+(typename __wrap_iter<_Iter1>::difference_type __n, __wrap_iter<_Iter1> __x) _NOEXCEPT {
__x += __n;
return __x;
}

#if _LIBCPP_STD_VER <= 17
#ifdef _LIBCPP_ABI_WRAP_ITER_ADL_PROOF
};

template <class _MutableIter, class _ConstIter>
using __wrap_mut_iter = typename __wrap_iter_impl<_MutableIter, _ConstIter>::template __wrap_iter<false>;
template <class _MutableIter, class _ConstIter>
using __wrap_const_iter = typename __wrap_iter_impl<_MutableIter, _ConstIter>::template __wrap_iter<true>;
#else
# if _LIBCPP_STD_VER <= 17
template <class _It>
struct __libcpp_is_contiguous_iterator<__wrap_iter<_It> > : true_type {};
#endif
# endif

template <class _It>
struct _LIBCPP_TEMPLATE_VIS pointer_traits<__wrap_iter<_It> > {
Expand All @@ -237,6 +282,12 @@ struct _LIBCPP_TEMPLATE_VIS pointer_traits<__wrap_iter<_It> > {
}
};

template <class _MutableIter, class _ConstIter>
using __wrap_mut_iter = __wrap_iter<_MutableIter>;
template <class _MutableIter, class _ConstIter>
using __wrap_const_iter = __wrap_iter<_ConstIter>;
#endif

_LIBCPP_END_NAMESPACE_STD

#endif // _LIBCPP___ITERATOR_WRAP_ITER_H
Loading
Loading