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 unqualified_lookup_wrapper(I i)22 constexpr explicit unqualified_lookup_wrapper(I i) noexcept : base_(std::move(i)) {} 23 decltype(auto)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. decltype(auto)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 }; iter_move(unscoped_enum & e)51constexpr unscoped_enum iter_move(unscoped_enum& e) noexcept(false) { return e; } 52 53 enum class scoped_enum { a, b, c }; iter_move(scoped_enum &)54constexpr scoped_enum* iter_move(scoped_enum&) noexcept { return nullptr; } 55 56 union some_union { 57 int x; 58 double y; 59 }; iter_move(some_union & u)60constexpr 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; move_tracker(move_tracker && other)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 moves()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