1 | // -*- C++ -*- |
2 | //===----------------------------------------------------------------------===// |
3 | // |
4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
5 | // See https://llvm.org/LICENSE.txt for license information. |
6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
7 | // |
8 | //===----------------------------------------------------------------------===// |
9 | |
10 | #ifndef LIBCPP_TEST_STD_UTILITIES_MEMORY_SPECIALIZED_ALGORITHMS_OVERLOAD_COMPARE_ITERATOR_H |
11 | #define LIBCPP_TEST_STD_UTILITIES_MEMORY_SPECIALIZED_ALGORITHMS_OVERLOAD_COMPARE_ITERATOR_H |
12 | |
13 | #include <iterator> |
14 | #include <memory> |
15 | |
16 | #include "test_macros.h" |
17 | |
18 | // An iterator type that overloads operator== and operator!= without any constraints, which |
19 | // can trip up some algorithms if we compare iterators against types that we're not allowed to. |
20 | // |
21 | // See https://github.com/llvm/llvm-project/issues/69334 for details. |
22 | template <class Iterator> |
23 | struct overload_compare_iterator { |
24 | using value_type = typename std::iterator_traits<Iterator>::value_type; |
25 | using difference_type = typename std::iterator_traits<Iterator>::difference_type; |
26 | using reference = typename std::iterator_traits<Iterator>::reference; |
27 | using pointer = typename std::iterator_traits<Iterator>::pointer; |
28 | using iterator_category = typename std::iterator_traits<Iterator>::iterator_category; |
29 | |
30 | overload_compare_iterator() = default; |
31 | |
32 | explicit overload_compare_iterator(Iterator it) : it_(it) {} |
33 | |
34 | overload_compare_iterator(overload_compare_iterator const&) = default; |
35 | overload_compare_iterator(overload_compare_iterator&&) = default; |
36 | overload_compare_iterator& operator=(overload_compare_iterator const&) = default; |
37 | overload_compare_iterator& operator=(overload_compare_iterator&&) = default; |
38 | |
39 | reference operator*() const TEST_NOEXCEPT { return *it_; } |
40 | |
41 | pointer operator->() const TEST_NOEXCEPT { return std::addressof(*it_); } |
42 | |
43 | overload_compare_iterator& operator++() TEST_NOEXCEPT { |
44 | ++it_; |
45 | return *this; |
46 | } |
47 | |
48 | overload_compare_iterator operator++(int) const TEST_NOEXCEPT { |
49 | overload_compare_iterator old(*this); |
50 | ++(*this); |
51 | return old; |
52 | } |
53 | |
54 | bool operator==(overload_compare_iterator const& other) const TEST_NOEXCEPT { return this->it_ == other.it_; } |
55 | |
56 | bool operator!=(overload_compare_iterator const& other) const TEST_NOEXCEPT { return !this->operator==(other); } |
57 | |
58 | // Hostile overloads |
59 | template <class Sentinel> |
60 | friend bool operator==(overload_compare_iterator const& lhs, Sentinel const& rhs) TEST_NOEXCEPT { |
61 | return static_cast<Iterator const&>(lhs) == rhs; |
62 | } |
63 | |
64 | template <class Sentinel> |
65 | friend bool operator!=(overload_compare_iterator const& lhs, Sentinel const& rhs) TEST_NOEXCEPT { |
66 | return static_cast<Iterator const&>(lhs) != rhs; |
67 | } |
68 | |
69 | private: |
70 | Iterator it_; |
71 | }; |
72 | |
73 | #endif // LIBCPP_TEST_STD_UTILITIES_MEMORY_SPECIALIZED_ALGORITHMS_OVERLOAD_COMPARE_ITERATOR_H |
74 | |