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, c++20 10 // UNSUPPORTED: libcpp-has-no-incomplete-ranges 11 12 // constexpr explicit zip_view(Views...) 13 14 #include <ranges> 15 #include <tuple> 16 17 #include "types.h" 18 19 template <class T> 20 void conversion_test(T); 21 22 template <class T, class... Args> 23 concept implicitly_constructible_from = requires(Args&&... args) { conversion_test<T>({std::move(args)...}); }; 24 25 // test constructor is explicit 26 static_assert(std::constructible_from<std::ranges::zip_view<SimpleCommon>, SimpleCommon>); 27 static_assert(!implicitly_constructible_from<std::ranges::zip_view<SimpleCommon>, SimpleCommon>); 28 29 static_assert(std::constructible_from<std::ranges::zip_view<SimpleCommon, SimpleCommon>, SimpleCommon, SimpleCommon>); 30 static_assert( 31 !implicitly_constructible_from<std::ranges::zip_view<SimpleCommon, SimpleCommon>, SimpleCommon, SimpleCommon>); 32 33 struct MoveAwareView : std::ranges::view_base { 34 int moves = 0; 35 constexpr MoveAwareView() = default; 36 constexpr MoveAwareView(MoveAwareView&& other) : moves(other.moves + 1) { other.moves = 1; } 37 constexpr MoveAwareView& operator=(MoveAwareView&& other) { 38 moves = other.moves + 1; 39 other.moves = 0; 40 return *this; 41 } 42 constexpr const int* begin() const { return &moves; } 43 constexpr const int* end() const { return &moves + 1; } 44 }; 45 46 template <class View1, class View2> 47 constexpr void constructorTest(auto&& buffer1, auto&& buffer2) { 48 std::ranges::zip_view v{View1{buffer1}, View2{buffer2}}; 49 auto [i, j] = *v.begin(); 50 assert(i == buffer1[0]); 51 assert(j == buffer2[0]); 52 }; 53 54 constexpr bool test() { 55 56 int buffer[8] = {1, 2, 3, 4, 5, 6, 7, 8}; 57 int buffer2[4] = {9, 8, 7, 6}; 58 59 { 60 // constructor from views 61 std::ranges::zip_view v(SizedRandomAccessView{buffer}, std::views::iota(0), std::ranges::single_view(2.)); 62 auto [i, j, k] = *v.begin(); 63 assert(i == 1); 64 assert(j == 0); 65 assert(k == 2.0); 66 } 67 68 { 69 // arguments are moved once 70 MoveAwareView mv; 71 std::ranges::zip_view v{std::move(mv), MoveAwareView{}}; 72 auto [numMoves1, numMoves2] = *v.begin(); 73 assert(numMoves1 == 2); // one move from the local variable to parameter, one move from parameter to member 74 assert(numMoves2 == 1); 75 } 76 77 // input and forward 78 { 79 constructorTest<InputCommonView, ForwardSizedView>(buffer, buffer2); 80 } 81 82 // bidi and random_access 83 { 84 constructorTest<BidiCommonView, SizedRandomAccessView>(buffer, buffer2); 85 } 86 87 // contiguous 88 { 89 constructorTest<ContiguousCommonView, ContiguousCommonView>(buffer, buffer2); 90 } 91 92 return true; 93 } 94 95 int main(int, char**) { 96 test(); 97 static_assert(test()); 98 99 return 0; 100 } 101