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 // UNSUPPORTED: libcpp-has-no-incomplete-ranges
11 
12 // constexpr auto size() requires sized_range<R>
13 // constexpr auto size() const requires sized_range<const R>
14 
15 #include <ranges>
16 
17 #include <array>
18 #include <cassert>
19 #include <concepts>
20 
21 #include "test_iterators.h"
22 #include "test_macros.h"
23 
24 template <class T>
25 concept HasSize = requires (T t) {
26   t.size();
27 };
28 
test()29 constexpr bool test()
30 {
31   {
32     struct SubtractableIters {
33       forward_iterator<int*> begin();
34       sized_sentinel<forward_iterator<int*>> end();
35     };
36     using OwningView = std::ranges::owning_view<SubtractableIters>;
37     static_assert(std::ranges::sized_range<OwningView&>);
38     static_assert(!std::ranges::range<const OwningView&>); // no begin/end
39     static_assert(HasSize<OwningView&>);
40     static_assert(HasSize<OwningView&&>);
41     static_assert(!HasSize<const OwningView&>);
42     static_assert(!HasSize<const OwningView&&>);
43   }
44   {
45     struct NoSize {
46       bidirectional_iterator<int*> begin();
47       bidirectional_iterator<int*> end();
48     };
49     using OwningView = std::ranges::owning_view<NoSize>;
50     static_assert(!HasSize<OwningView&>);
51     static_assert(!HasSize<OwningView&&>);
52     static_assert(!HasSize<const OwningView&>);
53     static_assert(!HasSize<const OwningView&&>);
54   }
55   {
56     struct SizeMember {
57       bidirectional_iterator<int*> begin();
58       bidirectional_iterator<int*> end();
59       int size() const;
60     };
61     using OwningView = std::ranges::owning_view<SizeMember>;
62     static_assert(std::ranges::sized_range<OwningView&>);
63     static_assert(!std::ranges::range<const OwningView&>); // no begin/end
64     static_assert(HasSize<OwningView&>);
65     static_assert(HasSize<OwningView&&>);
66     static_assert(!HasSize<const OwningView&>); // not a range, therefore no size()
67     static_assert(!HasSize<const OwningView&&>);
68   }
69   {
70     // Test an empty view.
71     int a[] = {1};
72     auto ov = std::ranges::owning_view(std::ranges::subrange(a, a));
73     assert(ov.size() == 0);
74     assert(std::as_const(ov).size() == 0);
75   }
76   {
77     // Test a non-empty view.
78     int a[] = {1};
79     auto ov = std::ranges::owning_view(std::ranges::subrange(a, a+1));
80     assert(ov.size() == 1);
81     assert(std::as_const(ov).size() == 1);
82   }
83   {
84     // Test a non-view.
85     std::array<int, 2> a = {1, 2};
86     auto ov = std::ranges::owning_view(std::move(a));
87     assert(ov.size() == 2);
88     assert(std::as_const(ov).size() == 2);
89   }
90   return true;
91 }
92 
main(int,char **)93 int main(int, char**) {
94   test();
95   static_assert(test());
96 
97   return 0;
98 }
99