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.
23template <class Iterator>
24struct 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
74private:
75 Iterator it_;
76};
77
78#endif // LIBCPP_TEST_STD_UTILITIES_MEMORY_SPECIALIZED_ALGORITHMS_OVERLOAD_COMPARE_ITERATOR_H
79

source code of libcxx/test/std/utilities/memory/specialized.algorithms/overload_compare_iterator.h