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