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 | |
15 | namespace check_unqualified_lookup { |
16 | // Wrapper around an iterator for testing unqualified calls to `iter_move` and `iter_swap`. |
17 | template <typename I> |
18 | class unqualified_lookup_wrapper { |
19 | public: |
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 | |
43 | private: |
44 | I base_ = I{}; |
45 | }; |
46 | |
47 | template <class It> |
48 | unqualified_lookup_wrapper(It) -> unqualified_lookup_wrapper<It>; |
49 | |
50 | enum unscoped_enum { a, b, c }; |
51 | constexpr unscoped_enum iter_move(unscoped_enum& e) noexcept(false) { return e; } |
52 | |
53 | enum class scoped_enum { a, b, c }; |
54 | constexpr scoped_enum* iter_move(scoped_enum&) noexcept { return nullptr; } |
55 | |
56 | union some_union { |
57 | int x; |
58 | double y; |
59 | }; |
60 | constexpr int iter_move(some_union& u) noexcept(false) { return u.x; } |
61 | |
62 | } // namespace check_unqualified_lookup |
63 | |
64 | class move_tracker { |
65 | public: |
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 | |
79 | private: |
80 | int moves_ = 0; |
81 | }; |
82 | |
83 | #endif // LIBCPP_TEST_STD_ITERATOR_UNQUALIFIED_LOOKUP_WRAPPER |
84 | |