185 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// template<class R>12// concept viewable_range;13 14#include <ranges>15#include <type_traits>16 17#include "test_iterators.h"18#include "test_range.h"19 20// The constraints we have in viewable_range are:21// range<T>22// view<remove_cvref_t<T>>23// constructible_from<remove_cvref_t<T>, T>24// lvalue_reference_t<T> || movable<remove_reference_t<T>>25// is-initializer-list<T>26//27// We test all the relevant combinations of satisfying/not satisfying those constraints.28 29// viewable_range<T> is not satisfied for (range=false, view=*, constructible_from=*, lvalue-or-movable=*)30struct T1 { };31static_assert(!std::ranges::range<T1>);32 33static_assert(!std::ranges::viewable_range<T1>);34static_assert(!std::ranges::viewable_range<T1&>);35static_assert(!std::ranges::viewable_range<T1&&>);36static_assert(!std::ranges::viewable_range<T1 const>);37static_assert(!std::ranges::viewable_range<T1 const&>);38static_assert(!std::ranges::viewable_range<T1 const&&>);39 40// viewable_range<T> is satisfied for (range=true, view=true, constructible_from=true, lvalue-or-movable=true)41struct T2 : test_range<cpp20_input_iterator>, std::ranges::view_base {42 T2(T2 const&) = default;43};44static_assert(std::ranges::range<T2>);45static_assert(std::ranges::view<T2>);46static_assert(std::constructible_from<T2, T2>);47 48static_assert(std::ranges::viewable_range<T2>);49static_assert(std::ranges::viewable_range<T2&>);50static_assert(std::ranges::viewable_range<T2&&>);51static_assert(std::ranges::viewable_range<T2 const>);52static_assert(std::ranges::viewable_range<T2 const&>);53static_assert(std::ranges::viewable_range<T2 const&&>);54 55// viewable_range<T> is satisfied for (range=true, view=true, constructible_from=true, lvalue-or-movable=false)56struct T3 : test_range<cpp20_input_iterator>, std::ranges::view_base {57 T3(T3 const&) = default;58};59static_assert(std::ranges::range<T3>);60static_assert(std::ranges::view<T3>);61static_assert(std::constructible_from<T3, T3>);62 63static_assert(std::ranges::viewable_range<T3>);64static_assert(std::ranges::viewable_range<T3&>);65static_assert(std::ranges::viewable_range<T3&&>);66static_assert(std::ranges::viewable_range<T3 const>);67static_assert(std::ranges::viewable_range<T3 const&>);68static_assert(std::ranges::viewable_range<T3 const&&>);69 70// viewable_range<T> is not satisfied for (range=true, view=true, constructible_from=false, lvalue-or-movable=true)71struct T4 : test_range<cpp20_input_iterator>, std::ranges::view_base {72 T4(T4 const&) = delete;73 T4(T4&&) = default; // necessary to model view74 T4& operator=(T4&&) = default; // necessary to model view75};76static_assert(std::ranges::range<T4 const&>);77static_assert(std::ranges::view<std::remove_cvref_t<T4 const&>>);78static_assert(!std::constructible_from<std::remove_cvref_t<T4 const&>, T4 const&>);79 80static_assert(!std::ranges::viewable_range<T4 const&>);81 82// A type that satisfies (range=true, view=true, constructible_from=false, lvalue-or-movable=false) can't be formed,83// because views are movable by definition84 85// viewable_range<T> is satisfied for (range=true, view=false, constructible_from=true, lvalue-or-movable=true)...86struct T5 : test_range<cpp20_input_iterator> { };87static_assert( std::ranges::range<T5>);88static_assert(!std::ranges::view<T5>);89static_assert( std::constructible_from<T5, T5>);90static_assert( std::movable<T5>);91static_assert(!std::movable<const T5>);92 93static_assert( std::ranges::viewable_range<T5>); // movable94static_assert( std::ranges::viewable_range<T5&>); // movable95static_assert( std::ranges::viewable_range<T5&&>); // movable96static_assert(!std::ranges::viewable_range<const T5>);97static_assert( std::ranges::viewable_range<const T5&>); // lvalue98static_assert(!std::ranges::viewable_range<const T5&&>);99 100// ...but not if the (non-view, lvalue-or-movable) range is an initializer_list.101static_assert( std::ranges::range<std::initializer_list<int>>);102static_assert(!std::ranges::view<std::initializer_list<int>>);103static_assert( std::constructible_from<std::initializer_list<int>, std::initializer_list<int>>);104static_assert( std::movable<std::initializer_list<int>>);105 106static_assert(!std::ranges::viewable_range<std::initializer_list<int>>);107static_assert( std::ranges::viewable_range<std::initializer_list<int>&>);108static_assert(!std::ranges::viewable_range<std::initializer_list<int>&&>);109static_assert(!std::ranges::viewable_range<std::initializer_list<int> const>);110static_assert( std::ranges::viewable_range<std::initializer_list<int> const&>);111static_assert(!std::ranges::viewable_range<std::initializer_list<int> const&&>);112 113// viewable_range<T> is not satisfied for (range=true, view=false, constructible_from=true, lvalue-or-movable=false)114struct T6 : test_range<cpp20_input_iterator> { T6(T6&&); T6& operator=(T6&&) = delete; };115static_assert( std::ranges::range<T6>);116static_assert(!std::ranges::view<T6>);117static_assert( std::constructible_from<T6, T6>);118static_assert(!std::movable<T6>);119 120static_assert(!std::ranges::viewable_range<T6>);121static_assert( std::ranges::viewable_range<T6&>); // lvalue122static_assert(!std::ranges::viewable_range<T6&&>);123static_assert(!std::ranges::viewable_range<const T6>);124static_assert( std::ranges::viewable_range<const T6&>); // lvalue125static_assert(!std::ranges::viewable_range<const T6&&>);126 127// viewable_range<T> is satisfied for (range=true, view=false, constructible_from=false, lvalue-or-movable=true)128struct T7 : test_range<cpp20_input_iterator> {129 T7(T7 const&) = delete;130};131static_assert(std::ranges::range<T7&>);132static_assert(!std::ranges::view<std::remove_cvref_t<T7&>>);133static_assert(!std::constructible_from<std::remove_cvref_t<T7&>, T7&>);134 135static_assert(!std::ranges::viewable_range<T7>);136static_assert( std::ranges::viewable_range<T7&>);137static_assert(!std::ranges::viewable_range<T7&&>);138static_assert(!std::ranges::viewable_range<const T7>);139static_assert( std::ranges::viewable_range<const T7&>);140static_assert(!std::ranges::viewable_range<const T7&&>);141 142// viewable_range<T> is not satisfied for (range=true, view=false, constructible_from=false, lvalue-or-movable=false)143struct T8 : test_range<cpp20_input_iterator> {144 T8(T8 const&) = delete;145};146static_assert(std::ranges::range<T8>);147static_assert(!std::ranges::view<T8>);148static_assert(!std::constructible_from<T8, T8>);149 150static_assert(!std::ranges::viewable_range<T8>);151static_assert( std::ranges::viewable_range<T8&>);152static_assert(!std::ranges::viewable_range<T8&&>);153static_assert(!std::ranges::viewable_range<const T8>);154static_assert( std::ranges::viewable_range<const T8&>);155static_assert(!std::ranges::viewable_range<const T8&&>);156 157// Test with a few degenerate types158static_assert(!std::ranges::viewable_range<void>);159static_assert(!std::ranges::viewable_range<int>);160static_assert(!std::ranges::viewable_range<int (*)(char)>);161static_assert(!std::ranges::viewable_range<int[]>);162static_assert(!std::ranges::viewable_range<int[10]>);163static_assert(!std::ranges::viewable_range<int(&)[]>); // not a range164static_assert( std::ranges::viewable_range<int(&)[10]>); // OK, lvalue165static_assert(!std::ranges::viewable_range<int(&&)[]>);166static_assert(!std::ranges::viewable_range<int(&&)[10]>);167 168// Test ADL-proofing.169struct Incomplete;170template<class T> struct Holder { T t; };171 172static_assert(!std::ranges::viewable_range<Holder<Incomplete>*>);173static_assert(!std::ranges::viewable_range<Holder<Incomplete>*&>);174static_assert(!std::ranges::viewable_range<Holder<Incomplete>*&&>);175static_assert(!std::ranges::viewable_range<Holder<Incomplete>* const>);176static_assert(!std::ranges::viewable_range<Holder<Incomplete>* const&>);177static_assert(!std::ranges::viewable_range<Holder<Incomplete>* const&&>);178 179static_assert(!std::ranges::viewable_range<Holder<Incomplete>*[10]>);180static_assert( std::ranges::viewable_range<Holder<Incomplete>*(&)[10]>);181static_assert(!std::ranges::viewable_range<Holder<Incomplete>*(&&)[10]>);182static_assert(!std::ranges::viewable_range<Holder<Incomplete>* const[10]>);183static_assert( std::ranges::viewable_range<Holder<Incomplete>* const(&)[10]>);184static_assert(!std::ranges::viewable_range<Holder<Incomplete>* const(&&)[10]>);185