[libcxx-commits] [PATCH] D130835: [libc++] Fix a hard error in `contiguous_iterator<NoOperatorArrowIter>`.
Konstantin Varlamov via Phabricator via libcxx-commits
libcxx-commits at lists.llvm.org
Sun Jul 31 02:10:23 PDT 2022
var-const created this revision.
Herald added a project: All.
var-const requested review of this revision.
Herald added a project: libc++.
Herald added a subscriber: libcxx-commits.
Herald added a reviewer: libc++.
Evaluating `contiguous_iterator` on an iterator that satisfies all the
constraints except the `to_address` constraint and doesn't have
`operator->` defined results in a hard error. This is because
`to_address` doesn't SFINAE away when given a type it cannot handle.
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D130835
Files:
libcxx/include/__memory/pointer_traits.h
libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.random.access/contiguous_iterator.compile.pass.cpp
Index: libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.random.access/contiguous_iterator.compile.pass.cpp
===================================================================
--- libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.random.access/contiguous_iterator.compile.pass.cpp
+++ libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.random.access/contiguous_iterator.compile.pass.cpp
@@ -13,6 +13,7 @@
#include <iterator>
#include <compare>
+#include <memory>
#include "test_iterators.h"
@@ -208,3 +209,45 @@
// Template param is used instead of element_type.
static_assert(std::random_access_iterator<template_and_no_element_type<int>>);
static_assert(std::contiguous_iterator<template_and_no_element_type<int>>);
+
+template <bool DisableArrow, bool DisableToAddress = true>
+struct no_operator_arrow {
+ typedef std::contiguous_iterator_tag iterator_category;
+ typedef int value_type;
+ typedef int element_type;
+ typedef std::ptrdiff_t difference_type;
+ typedef int* pointer;
+ typedef int& reference;
+ typedef no_operator_arrow self;
+
+ no_operator_arrow();
+
+ reference operator*() const;
+ pointer operator->() const requires (!DisableArrow);
+ auto operator<=>(const self&) const = default;
+
+ self& operator++();
+ self operator++(int);
+
+ self& operator--();
+ self operator--(int);
+
+ self& operator+=(difference_type n);
+ self operator+(difference_type n) const;
+ friend self operator+(difference_type n, self x);
+
+ self& operator-=(difference_type n);
+ self operator-(difference_type n) const;
+ difference_type operator-(const self& n) const;
+
+ reference operator[](difference_type n) const;
+};
+
+template<>
+struct std::pointer_traits<no_operator_arrow</*DisableArrow=*/true, /*DisableToAddress=*/false>> {
+ static constexpr int *to_address(const no_operator_arrow<true, false>&);
+};
+
+static_assert(std::contiguous_iterator<no_operator_arrow</*DisableArrow=*/false>>);
+static_assert(!std::contiguous_iterator<no_operator_arrow</*DisableArrow=*/true>>);
+static_assert(std::contiguous_iterator<no_operator_arrow</*DisableArrow=*/true, /*DisableToAddress=*/false>>);
Index: libcxx/include/__memory/pointer_traits.h
===================================================================
--- libcxx/include/__memory/pointer_traits.h
+++ libcxx/include/__memory/pointer_traits.h
@@ -171,9 +171,26 @@
return __p;
}
+template <class _Pointer, class = void>
+struct _HasToAddress : false_type {};
+
+template <class _Pointer>
+struct _HasToAddress<_Pointer,
+ decltype((void)&pointer_traits<_Pointer>::to_address)
+> : true_type {};
+
+template <class _Pointer, class = void>
+struct _HasArrow : false_type {};
+
+template <class _Pointer>
+struct _HasArrow<_Pointer,
+ decltype((void)declval<const _Pointer&>().operator->())
+> : true_type {};
+
// enable_if is needed here to avoid instantiating checks for fancy pointers on raw pointers
template <class _Pointer, class = __enable_if_t<
- !is_pointer<_Pointer>::value && !is_array<_Pointer>::value && !is_function<_Pointer>::value
+ !is_pointer<_Pointer>::value && !is_array<_Pointer>::value && !is_function<_Pointer>::value &&
+ (_HasArrow<_Pointer>::value || _HasToAddress<_Pointer>::value)
> >
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
typename decay<decltype(__to_address_helper<_Pointer>::__call(declval<const _Pointer&>()))>::type
@@ -208,7 +225,7 @@
template <class _Pointer>
inline _LIBCPP_INLINE_VISIBILITY constexpr
-auto to_address(const _Pointer& __p) noexcept {
+auto to_address(const _Pointer& __p) noexcept -> decltype(std::__to_address(__p)) {
return _VSTD::__to_address(__p);
}
#endif
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D130835.448845.patch
Type: text/x-patch
Size: 3946 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/libcxx-commits/attachments/20220731/c5c94137/attachment-0001.bin>
More information about the libcxx-commits
mailing list