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 auto size() requires(sized_range<Views>&&...)
13 // constexpr auto size() const requires(sized_range<const Views>&&...)
14 
15 #include <ranges>
16 
17 #include <cassert>
18 #include <tuple>
19 #include <utility>
20 
21 #include "test_iterators.h"
22 #include "types.h"
23 
24 int buffer[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
25 struct View : std::ranges::view_base {
26   std::size_t size_ = 0;
ViewView27   constexpr View(std::size_t s) : size_(s) {}
beginView28   constexpr auto begin() const { return buffer; }
endView29   constexpr auto end() const { return buffer + size_; }
30 };
31 
32 struct SizedNonConst : std::ranges::view_base {
33   using iterator = forward_iterator<int*>;
34   std::size_t size_ = 0;
SizedNonConstSizedNonConst35   constexpr SizedNonConst(std::size_t s) : size_(s) {}
beginSizedNonConst36   constexpr auto begin() const { return iterator{buffer}; }
endSizedNonConst37   constexpr auto end() const { return iterator{buffer + size_}; }
sizeSizedNonConst38   constexpr std::size_t size() { return size_; }
39 };
40 
41 struct StrangeSizeView : std::ranges::view_base {
beginStrangeSizeView42   constexpr auto begin() const { return buffer; }
endStrangeSizeView43   constexpr auto end() const { return buffer + 8; }
44 
sizeStrangeSizeView45   constexpr auto size() { return 5; }
sizeStrangeSizeView46   constexpr auto size() const { return 6; }
47 };
48 
test()49 constexpr bool test() {
50   {
51     // single range
52     std::ranges::zip_view v(View(8));
53     assert(v.size() == 8);
54     assert(std::as_const(v).size() == 8);
55   }
56 
57   {
58     // multiple ranges same type
59     std::ranges::zip_view v(View(2), View(3));
60     assert(v.size() == 2);
61     assert(std::as_const(v).size() == 2);
62   }
63 
64   {
65     // multiple ranges different types
66     std::ranges::zip_view v(std::views::iota(0, 500), View(3));
67     assert(v.size() == 3);
68     assert(std::as_const(v).size() == 3);
69   }
70 
71   {
72     // const-view non-sized range
73     std::ranges::zip_view v(SizedNonConst(2), View(3));
74     assert(v.size() == 2);
75     static_assert(std::ranges::sized_range<decltype(v)>);
76     static_assert(!std::ranges::sized_range<decltype(std::as_const(v))>);
77   }
78 
79   {
80     // const/non-const has different sizes
81     std::ranges::zip_view v(StrangeSizeView{});
82     assert(v.size() == 5);
83     assert(std::as_const(v).size() == 6);
84   }
85 
86   {
87     // underlying range not sized
88     std::ranges::zip_view v(InputCommonView{buffer});
89     static_assert(!std::ranges::sized_range<decltype(v)>);
90     static_assert(!std::ranges::sized_range<decltype(std::as_const(v))>);
91   }
92   return true;
93 }
94 
main(int,char **)95 int main(int, char**) {
96   test();
97   static_assert(test());
98 
99   return 0;
100 }
101