304 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9// UNSUPPORTED: c++03, c++11, c++14, c++1710 11// constexpr auto end();12// constexpr auto end() const;13// requires forward_range<const V> &&14// is_reference_v<range_reference_t<const V>> &&15// input_range<range_reference_t<const V>>16 17#include <cassert>18#include <ranges>19#include <type_traits>20 21#include "test_macros.h"22#include "types.h"23 24template <class T>25concept HasConstEnd = requires (const T& t){26 t.end();27};28 29 30// | ID | outer | outer | outer | inner | inner | inner | end() | end() |31// | | simple | forward | common | l_ref | forward | common | | const |32// |----|--------|---------|--------|-------|---------|--------|---------------|--------------|33// | 1 | Y | Y | Y | Y | Y | Y |iterator<true> |iterator<true>|34// | 2 | Y | Y | Y | Y | Y | N |sentinel<true> |sentinel<true>|35// | 3 | Y | Y | Y | Y | N | Y |sentinel<true> |sentinel<true>|36// | 4 | Y | Y | Y | N | Y | Y |sentinel<true> | - |37// | 5 | Y | Y | N | Y | Y | Y |sentinel<true> |sentinel<true>|38// | 6 | Y | N | Y | Y | Y | Y |sentinel<true> | - |39// | 7 | N | Y | Y | Y | Y | Y |iterator<false>|iterator<true>|40// | 8 | N | Y | Y | Y | Y | N |sentinel<false>|sentinel<true>|41// | 9 | N | Y | Y | Y | N | Y |sentinel<false>|sentinel<true>|42// | 10 | N | Y | Y | N | Y | Y |sentinel<false>| - |43// | 11 | N | Y | N | Y | Y | Y |sentinel<false>|sentinel<true>|44// | 12 | N | N | Y | Y | Y | Y |sentinel<false>| - |45//46//47 48struct ConstNotRange : std::ranges::view_base {49 const ChildView* begin();50 const ChildView* end();51};52 53constexpr bool test() {54 int buffer[4][4] = {{1111, 2222, 3333, 4444}, {555, 666, 777, 888}, {99, 1010, 1111, 1212}, {13, 14, 15, 16}};55 56 {57 // test ID 158 ForwardCommonInner inners[4] = {buffer[0], buffer[1], buffer[2], buffer[3]};59 SimpleForwardCommonOuter<ForwardCommonInner> outer{inners};60 61 std::ranges::join_view jv(outer);62 assert(jv.end() == std::ranges::next(jv.begin(), 16));63 assert(std::as_const(jv).end() == std::ranges::next(std::as_const(jv).begin(), 16));64 65 static_assert(HasConstEnd<decltype(jv)>);66 static_assert(std::same_as<decltype(jv.end()), decltype(std::as_const(jv).end())>);67 static_assert(std::ranges::common_range<decltype(jv)>);68 static_assert(std::ranges::common_range<const decltype(jv)>);69 }70 71 {72 // test ID 273 ForwardNonCommonInner inners[3] = {buffer[0], buffer[1], buffer[2]};74 SimpleForwardCommonOuter<ForwardNonCommonInner> outer{inners};75 76 std::ranges::join_view jv(outer);77 assert(jv.end() == std::ranges::next(jv.begin(), 12));78 assert(std::as_const(jv).end() == std::ranges::next(std::as_const(jv).begin(), 12));79 80 static_assert(HasConstEnd<decltype(jv)>);81 static_assert(std::same_as<decltype(jv.end()), decltype(std::as_const(jv).end())>);82 static_assert(!std::ranges::common_range<decltype(jv)>);83 static_assert(!std::ranges::common_range<const decltype(jv)>);84 }85 86 {87 // test ID 388 InputCommonInner inners[3] = {buffer[0], buffer[1], buffer[2]};89 SimpleForwardCommonOuter<InputCommonInner> outer{inners};90 91 std::ranges::join_view jv(outer);92 assert(jv.end() == std::ranges::next(jv.begin(), 12));93 assert(std::as_const(jv).end() == std::ranges::next(std::as_const(jv).begin(), 12));94 95 static_assert(HasConstEnd<decltype(jv)>);96 static_assert(std::same_as<decltype(jv.end()), decltype(std::as_const(jv).end())>);97 static_assert(!std::ranges::common_range<decltype(jv)>);98 static_assert(!std::ranges::common_range<const decltype(jv)>);99 }100 101 {102 // test ID 4103 ForwardCommonInner inners[2] = {buffer[0], buffer[1]};104 InnerRValue<SimpleForwardCommonOuter<ForwardCommonInner>> outer{inners};105 106 std::ranges::join_view jv(outer);107 assert(jv.end() == std::ranges::next(jv.begin(), 8));108 109 static_assert(!HasConstEnd<decltype(jv)>);110 static_assert(!std::ranges::common_range<decltype(jv)>);111 static_assert(!std::ranges::common_range<const decltype(jv)>);112 }113 114 {115 // test ID 5116 ForwardCommonInner inners[4] = {buffer[0], buffer[1], buffer[2], buffer[3]};117 SimpleForwardNonCommonOuter<ForwardCommonInner> outer{inners};118 119 std::ranges::join_view jv(outer);120 assert(jv.end() == std::ranges::next(jv.begin(), 16));121 assert(std::as_const(jv).end() == std::ranges::next(std::as_const(jv).begin(), 16));122 123 static_assert(HasConstEnd<decltype(jv)>);124 static_assert(std::same_as<decltype(jv.end()), decltype(std::as_const(jv).end())>);125 static_assert(!std::ranges::common_range<decltype(jv)>);126 static_assert(!std::ranges::common_range<const decltype(jv)>);127 }128 129 {130 // test ID 6131 ForwardCommonInner inners[4] = {buffer[0], buffer[1], buffer[2], buffer[3]};132 SimpleInputCommonOuter<ForwardCommonInner> outer{inners};133 134 std::ranges::join_view jv(outer);135 assert(jv.end() == std::ranges::next(jv.begin(), 16));136 137 static_assert(!HasConstEnd<decltype(jv)>);138 static_assert(!std::ranges::common_range<decltype(jv)>);139 static_assert(!std::ranges::common_range<const decltype(jv)>);140 }141 142 {143 // test ID 7144 ForwardCommonInner inners[1] = {buffer[0]};145 NonSimpleForwardCommonOuter<ForwardCommonInner> outer{inners};146 147 std::ranges::join_view jv(outer);148 assert(jv.end() == std::ranges::next(jv.begin(), 4));149 assert(std::as_const(jv).end() == std::ranges::next(std::as_const(jv).begin(), 4));150 151 static_assert(HasConstEnd<decltype(jv)>);152 static_assert(!std::same_as<decltype(jv.end()), decltype(std::as_const(jv).end())>);153 static_assert(std::ranges::common_range<decltype(jv)>);154 static_assert(std::ranges::common_range<const decltype(jv)>);155 }156 157 {158 // test ID 8159 ForwardNonCommonInner inners[3] = {buffer[0], buffer[1], buffer[2]};160 NonSimpleForwardCommonOuter<ForwardNonCommonInner> outer{inners};161 162 std::ranges::join_view jv(outer);163 assert(jv.end() == std::ranges::next(jv.begin(), 12));164 assert(std::as_const(jv).end() == std::ranges::next(std::as_const(jv).begin(), 12));165 166 static_assert(HasConstEnd<decltype(jv)>);167 static_assert(!std::same_as<decltype(jv.end()), decltype(std::as_const(jv).end())>);168 static_assert(!std::ranges::common_range<decltype(jv)>);169 static_assert(!std::ranges::common_range<const decltype(jv)>);170 }171 172 {173 // test ID 9174 InputCommonInner inners[3] = {buffer[0], buffer[1], buffer[2]};175 NonSimpleForwardCommonOuter<InputCommonInner> outer{inners};176 177 std::ranges::join_view jv(outer);178 assert(jv.end() == std::ranges::next(jv.begin(), 12));179 assert(std::as_const(jv).end() == std::ranges::next(std::as_const(jv).begin(), 12));180 181 static_assert(HasConstEnd<decltype(jv)>);182 static_assert(!std::same_as<decltype(jv.end()), decltype(std::as_const(jv).end())>);183 static_assert(!std::ranges::common_range<decltype(jv)>);184 static_assert(!std::ranges::common_range<const decltype(jv)>);185 }186 187 {188 // test ID 10189 ForwardCommonInner inners[2] = {buffer[0], buffer[1]};190 InnerRValue<NonSimpleForwardCommonOuter<ForwardCommonInner>> outer{inners};191 192 std::ranges::join_view jv(outer);193 assert(jv.end() == std::ranges::next(jv.begin(), 8));194 195 static_assert(!HasConstEnd<decltype(jv)>);196 static_assert(!std::ranges::common_range<decltype(jv)>);197 static_assert(!std::ranges::common_range<const decltype(jv)>);198 }199 200 {201 // test ID 11202 ForwardCommonInner inners[4] = {buffer[0], buffer[1], buffer[2], buffer[3]};203 NonSimpleForwardNonCommonOuter<ForwardCommonInner> outer{inners};204 205 std::ranges::join_view jv(outer);206 assert(jv.end() == std::ranges::next(jv.begin(), 16));207 assert(std::as_const(jv).end() == std::ranges::next(std::as_const(jv).begin(), 16));208 209 static_assert(HasConstEnd<decltype(jv)>);210 static_assert(!std::same_as<decltype(jv.end()), decltype(std::as_const(jv).end())>);211 static_assert(!std::ranges::common_range<decltype(jv)>);212 static_assert(!std::ranges::common_range<const decltype(jv)>);213 }214 215 {216 // test ID 12217 ForwardCommonInner inners[4] = {buffer[0], buffer[1], buffer[2], buffer[3]};218 NonSimpleInputCommonOuter<ForwardCommonInner> outer{inners};219 220 std::ranges::join_view jv(outer);221 assert(jv.end() == std::ranges::next(jv.begin(), 16));222 223 static_assert(!HasConstEnd<decltype(jv)>);224 static_assert(!std::ranges::common_range<decltype(jv)>);225 static_assert(!std::ranges::common_range<const decltype(jv)>);226 }227 228 {229 std::ranges::join_view jv(ConstNotRange{});230 static_assert(!HasConstEnd<decltype(jv)>);231 }232 233 // Has some empty children.234 {235 CopyableChild children[4] = {CopyableChild(buffer[0], 4), CopyableChild(buffer[1], 0), CopyableChild(buffer[2], 1), CopyableChild(buffer[3], 0)};236 auto jv = std::ranges::join_view(ParentView(children));237 assert(jv.end() == std::ranges::next(jv.begin(), 5));238 }239 240 // Parent is empty.241 {242 CopyableChild children[4] = {CopyableChild(buffer[0]), CopyableChild(buffer[1]), CopyableChild(buffer[2]), CopyableChild(buffer[3])};243 std::ranges::join_view jv(ParentView(children, 0));244 assert(jv.end() == jv.begin());245 }246 247 // Parent size is one.248 {249 CopyableChild children[1] = {CopyableChild(buffer[0])};250 std::ranges::join_view jv(ParentView(children, 1));251 assert(jv.end() == std::ranges::next(jv.begin(), 4));252 }253 254 // Parent and child size is one.255 {256 CopyableChild children[1] = {CopyableChild(buffer[0], 1)};257 std::ranges::join_view jv(ParentView(children, 1));258 assert(jv.end() == std::ranges::next(jv.begin()));259 }260 261 // Parent size is one child is empty262 {263 CopyableChild children[1] = {CopyableChild(buffer[0], 0)};264 std::ranges::join_view jv(ParentView(children, 1));265 assert(jv.end() == jv.begin());266 }267 268 // Has all empty children.269 {270 CopyableChild children[4] = {CopyableChild(buffer[0], 0), CopyableChild(buffer[1], 0), CopyableChild(buffer[2], 0), CopyableChild(buffer[3], 0)};271 auto jv = std::ranges::join_view(ParentView(children));272 assert(jv.end() == jv.begin());273 }274 275 // First child is empty, others are not.276 {277 CopyableChild children[4] = {CopyableChild(buffer[0], 4), CopyableChild(buffer[1], 0), CopyableChild(buffer[2], 0), CopyableChild(buffer[3], 0)};278 auto jv = std::ranges::join_view(ParentView(children));279 assert(jv.end() == std::ranges::next(jv.begin(), 4));280 }281 282 // Last child is empty, others are not.283 {284 CopyableChild children[4] = {CopyableChild(buffer[0], 4), CopyableChild(buffer[1], 4), CopyableChild(buffer[2], 4), CopyableChild(buffer[3], 0)};285 auto jv = std::ranges::join_view(ParentView(children));286 assert(jv.end() == std::ranges::next(jv.begin(), 12));287 }288 289 // LWG3700: The `const begin` of the `join_view` family does not require `InnerRng` to be a range290 {291 std::ranges::join_view<ConstNonJoinableRange> jv;292 static_assert(!HasConstEnd<decltype(jv)>);293 }294 295 return true;296}297 298int main(int, char**) {299 test();300 static_assert(test());301 302 return 0;303}304