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 // UNSUPPORTED: c++03, c++11, c++14, c++17 10 11 // constexpr const iterator_t<Base>& base() const & noexcept; 12 // constexpr iterator_t<Base> base() &&; 13 14 #include <cassert> 15 #include <ranges> 16 #include <tuple> 17 #include <type_traits> 18 #include <utility> 19 20 #include "MoveOnly.h" 21 #include "../types.h" 22 23 // Test Noexcept 24 template <class T> 25 concept IsBaseNoexcept = 26 requires { 27 { std::declval<T>().base() } noexcept; 28 }; 29 30 using BaseView = std::ranges::subrange<std::tuple<int>*>; 31 using ElementsIter = std::ranges::iterator_t<std::ranges::elements_view<BaseView, 0>>; 32 33 static_assert(IsBaseNoexcept<const ElementsIter&>); 34 static_assert(IsBaseNoexcept<ElementsIter&>); 35 static_assert(IsBaseNoexcept<const ElementsIter&&>); 36 static_assert(!IsBaseNoexcept<ElementsIter&&>); 37 38 constexpr bool test() { 39 std::tuple<int> t{5}; 40 41 // const & 42 { 43 const ElementsIter it{&t}; 44 decltype(auto) base = it.base(); 45 static_assert(std::is_same_v<decltype(base), std::tuple<int>* const&>); 46 assert(base == &t); 47 } 48 49 // & 50 { 51 ElementsIter it{&t}; 52 decltype(auto) base = it.base(); 53 static_assert(std::is_same_v<decltype(base), std::tuple<int>* const&>); 54 assert(base == &t); 55 } 56 57 // && 58 { 59 ElementsIter it{&t}; 60 decltype(auto) base = std::move(it).base(); 61 static_assert(std::is_same_v<decltype(base), std::tuple<int>*>); 62 assert(base == &t); 63 } 64 65 // const && 66 { 67 const ElementsIter it{&t}; 68 decltype(auto) base = std::move(it).base(); 69 static_assert(std::is_same_v<decltype(base), std::tuple<int>* const&>); 70 assert(base == &t); 71 } 72 73 // move only 74 { 75 struct MoveOnlyIter : IterBase<MoveOnlyIter> { 76 MoveOnly mo; 77 }; 78 struct Sent { 79 constexpr bool operator==(const MoveOnlyIter&) const { return true; } 80 }; 81 82 using MoveOnlyElemIter = 83 std::ranges::iterator_t<std::ranges::elements_view<std::ranges::subrange<MoveOnlyIter, Sent>, 0>>; 84 85 MoveOnlyElemIter it{MoveOnlyIter{{}, MoveOnly{5}}}; 86 decltype(auto) base = std::move(it).base(); 87 static_assert(std::is_same_v<decltype(base), MoveOnlyIter>); 88 assert(base.mo.get() == 5); 89 } 90 91 return true; 92 } 93 94 int main(int, char**) { 95 test(); 96 static_assert(test()); 97 return 0; 98 } 99