1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef LIBCPP_TEST_STD_ITERATOR_UNQUALIFIED_LOOKUP_WRAPPER
10#define LIBCPP_TEST_STD_ITERATOR_UNQUALIFIED_LOOKUP_WRAPPER
11
12#include <iterator>
13#include <utility>
14
15namespace check_unqualified_lookup {
16// Wrapper around an iterator for testing unqualified calls to `iter_move` and `iter_swap`.
17template <typename I>
18class unqualified_lookup_wrapper {
19public:
20 unqualified_lookup_wrapper() = default;
21
22 constexpr explicit unqualified_lookup_wrapper(I i) noexcept : base_(std::move(i)) {}
23
24 constexpr decltype(auto) operator*() const noexcept { return *base_; }
25
26 constexpr unqualified_lookup_wrapper& operator++() noexcept {
27 ++base_;
28 return *this;
29 }
30
31 constexpr void operator++(int) noexcept { ++base_; }
32
33 constexpr bool operator==(unqualified_lookup_wrapper const& other) const noexcept {
34 return base_ == other.base_;
35 }
36
37 // Delegates `std::ranges::iter_move` for the underlying iterator. `noexcept(false)` will be used
38 // to ensure that the unqualified-lookup overload is chosen.
39 friend constexpr decltype(auto) iter_move(unqualified_lookup_wrapper& i) noexcept(false) {
40 return std::ranges::iter_move(i.base_);
41 }
42
43private:
44 I base_ = I{};
45};
46
47template <class It>
48unqualified_lookup_wrapper(It) -> unqualified_lookup_wrapper<It>;
49
50enum unscoped_enum { a, b, c };
51constexpr unscoped_enum iter_move(unscoped_enum& e) noexcept(false) { return e; }
52
53enum class scoped_enum { a, b, c };
54constexpr scoped_enum* iter_move(scoped_enum&) noexcept { return nullptr; }
55
56union some_union {
57 int x;
58 double y;
59};
60constexpr int iter_move(some_union& u) noexcept(false) { return u.x; }
61
62} // namespace check_unqualified_lookup
63
64class move_tracker {
65public:
66 move_tracker() = default;
67 constexpr move_tracker(move_tracker&& other) noexcept : moves_{other.moves_ + 1} { other.moves_ = 0; }
68 constexpr move_tracker& operator=(move_tracker&& other) noexcept {
69 moves_ = other.moves_ + 1;
70 other.moves_ = 0;
71 return *this;
72 }
73
74 move_tracker(move_tracker const& other) = delete;
75 move_tracker& operator=(move_tracker const& other) = delete;
76
77 constexpr int moves() const noexcept { return moves_; }
78
79private:
80 int moves_ = 0;
81};
82
83#endif // LIBCPP_TEST_STD_ITERATOR_UNQUALIFIED_LOOKUP_WRAPPER
84

source code of libcxx/test/std/iterators/iterator.requirements/iterator.cust/unqualified_lookup_wrapper.h