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 #include <type_traits> 16 17 #include "test_macros.h" 18 19 // An iterator type that overloads operator== and operator!= without any constraints, which 20 // can trip up some algorithms if we compare iterators against types that we're not allowed to. 21 // 22 // See https://github.com/llvm/llvm-project/issues/69334 for details. 23 template <class Iterator> 24 struct overload_compare_iterator { 25 static_assert( 26 std::is_base_of<std::forward_iterator_tag, typename std::iterator_traits<Iterator>::iterator_category>::value, 27 "overload_compare_iterator can only adapt forward iterators"); 28 29 using value_type = typename std::iterator_traits<Iterator>::value_type; 30 using difference_type = typename std::iterator_traits<Iterator>::difference_type; 31 using reference = typename std::iterator_traits<Iterator>::reference; 32 using pointer = typename std::iterator_traits<Iterator>::pointer; 33 using iterator_category = std::forward_iterator_tag; 34 35 overload_compare_iterator() = default; 36 37 explicit overload_compare_iterator(Iterator it) : it_(it) {} 38 39 overload_compare_iterator(overload_compare_iterator const&) = default; 40 overload_compare_iterator(overload_compare_iterator&&) = default; 41 overload_compare_iterator& operator=(overload_compare_iterator const&) = default; 42 overload_compare_iterator& operator=(overload_compare_iterator&&) = default; 43 44 reference operator*() const TEST_NOEXCEPT { return *it_; } 45 46 pointer operator->() const TEST_NOEXCEPT { return std::addressof(*it_); } 47 48 overload_compare_iterator& operator++() TEST_NOEXCEPT { 49 ++it_; 50 return *this; 51 } 52 53 overload_compare_iterator operator++(int) const TEST_NOEXCEPT { 54 overload_compare_iterator old(*this); 55 ++(*this); 56 return old; 57 } 58 59 bool operator==(overload_compare_iterator const& other) const TEST_NOEXCEPT { return this->it_ == other.it_; } 60 61 bool operator!=(overload_compare_iterator const& other) const TEST_NOEXCEPT { return !this->operator==(other); } 62 63 // Hostile overloads 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 template <class Sentinel> 70 friend bool operator!=(overload_compare_iterator const& lhs, Sentinel const& rhs) TEST_NOEXCEPT { 71 return static_cast<Iterator const&>(lhs) != rhs; 72 } 73 74 private: 75 Iterator it_; 76 }; 77 78 #endif // LIBCPP_TEST_STD_UTILITIES_MEMORY_SPECIALIZED_ALGORITHMS_OVERLOAD_COMPARE_ITERATOR_H 79