1*6777b538SAndroid Build Coastguard Worker// Copyright 2017 The Chromium Authors 2*6777b538SAndroid Build Coastguard Worker// Use of this source code is governed by a BSD-style license that can be 3*6777b538SAndroid Build Coastguard Worker// found in the LICENSE file. 4*6777b538SAndroid Build Coastguard Worker 5*6777b538SAndroid Build Coastguard Worker// This is a "No Compile Test" suite. 6*6777b538SAndroid Build Coastguard Worker// http://dev.chromium.org/developers/testing/no-compile-tests 7*6777b538SAndroid Build Coastguard Worker 8*6777b538SAndroid Build Coastguard Worker#include "base/containers/span.h" 9*6777b538SAndroid Build Coastguard Worker 10*6777b538SAndroid Build Coastguard Worker#include <array> 11*6777b538SAndroid Build Coastguard Worker#include <set> 12*6777b538SAndroid Build Coastguard Worker#include <string_view> 13*6777b538SAndroid Build Coastguard Worker#include <vector> 14*6777b538SAndroid Build Coastguard Worker 15*6777b538SAndroid Build Coastguard Worker 16*6777b538SAndroid Build Coastguard Worker 17*6777b538SAndroid Build Coastguard Workernamespace base { 18*6777b538SAndroid Build Coastguard Worker 19*6777b538SAndroid Build Coastguard Workerclass Base { 20*6777b538SAndroid Build Coastguard Worker}; 21*6777b538SAndroid Build Coastguard Worker 22*6777b538SAndroid Build Coastguard Workerclass Derived : Base { 23*6777b538SAndroid Build Coastguard Worker}; 24*6777b538SAndroid Build Coastguard Worker 25*6777b538SAndroid Build Coastguard Worker// A default constructed span must have an extent of 0 or dynamic_extent. 26*6777b538SAndroid Build Coastguard Workervoid DefaultSpanWithNonZeroStaticExtentDisallowed() { 27*6777b538SAndroid Build Coastguard Worker span<int, 1u> span; // expected-error {{no matching constructor for initialization of 'span<int, 1U>'}} 28*6777b538SAndroid Build Coastguard Worker} 29*6777b538SAndroid Build Coastguard Worker 30*6777b538SAndroid Build Coastguard Worker// A span with static extent constructed from an array must match the size of 31*6777b538SAndroid Build Coastguard Worker// the array. 32*6777b538SAndroid Build Coastguard Workervoid SpanFromArrayWithNonMatchingStaticExtentDisallowed() { 33*6777b538SAndroid Build Coastguard Worker int array[] = {1, 2, 3}; 34*6777b538SAndroid Build Coastguard Worker span<int, 1u> span(array); // expected-error {{no matching constructor for initialization of 'span<int, 1U>'}} 35*6777b538SAndroid Build Coastguard Worker} 36*6777b538SAndroid Build Coastguard Worker 37*6777b538SAndroid Build Coastguard Worker// A span with static extent constructed from another span must match the 38*6777b538SAndroid Build Coastguard Worker// extent. 39*6777b538SAndroid Build Coastguard Workervoid SpanFromOtherSpanWithMismatchingExtentDisallowed() { 40*6777b538SAndroid Build Coastguard Worker std::array<int, 3> array = {1, 2, 3}; 41*6777b538SAndroid Build Coastguard Worker span<int, 3u> span3(array); 42*6777b538SAndroid Build Coastguard Worker span<int, 4u> span4(span3); // expected-error {{no matching constructor for initialization of 'span<int, 4U>'}} 43*6777b538SAndroid Build Coastguard Worker} 44*6777b538SAndroid Build Coastguard Worker 45*6777b538SAndroid Build Coastguard Worker// Converting a dynamic span to a static span should not be allowed. 46*6777b538SAndroid Build Coastguard Workervoid DynamicSpanToStaticSpanDisallowed() { 47*6777b538SAndroid Build Coastguard Worker span<int> dynamic_span; 48*6777b538SAndroid Build Coastguard Worker span<int, 3u> static_span = dynamic_span; // expected-error-re {{no viable conversion from 'span<[...], (default) dynamic_extent aka {{.*}}>' to 'span<[...], 3>'}} 49*6777b538SAndroid Build Coastguard Worker} 50*6777b538SAndroid Build Coastguard Worker 51*6777b538SAndroid Build Coastguard Worker// Internally, this is represented as a pointer to pointers to Derived. An 52*6777b538SAndroid Build Coastguard Worker// implicit conversion to a pointer to pointers to Base must not be allowed. 53*6777b538SAndroid Build Coastguard Worker// If it were allowed, then something like this would be possible: 54*6777b538SAndroid Build Coastguard Worker// Cat** cats = GetCats(); 55*6777b538SAndroid Build Coastguard Worker// Animals** animals = cats; 56*6777b538SAndroid Build Coastguard Worker// animals[0] = new Dog(); // Uh oh! 57*6777b538SAndroid Build Coastguard Workervoid DerivedToBaseConversionDisallowed() { 58*6777b538SAndroid Build Coastguard Worker span<Derived*> derived_span; 59*6777b538SAndroid Build Coastguard Worker span<Base*> base_span(derived_span); // expected-error {{no matching constructor for initialization of 'span<Base *>'}} 60*6777b538SAndroid Build Coastguard Worker} 61*6777b538SAndroid Build Coastguard Worker 62*6777b538SAndroid Build Coastguard Worker// Similarly, converting a span<int*> to span<const int*> requires internally 63*6777b538SAndroid Build Coastguard Worker// converting T** to const T**. This is also disallowed, as it would allow code 64*6777b538SAndroid Build Coastguard Worker// to violate the contract of const. 65*6777b538SAndroid Build Coastguard Workervoid PtrToConstPtrConversionDisallowed() { 66*6777b538SAndroid Build Coastguard Worker span<int*> non_const_span; 67*6777b538SAndroid Build Coastguard Worker span<const int*> const_span(non_const_span); // expected-error {{no matching constructor for initialization of 'span<const int *>'}} 68*6777b538SAndroid Build Coastguard Worker} 69*6777b538SAndroid Build Coastguard Worker 70*6777b538SAndroid Build Coastguard Worker// A const container should not be convertible to a mutable span. 71*6777b538SAndroid Build Coastguard Workervoid ConstContainerToMutableConversionDisallowed() { 72*6777b538SAndroid Build Coastguard Worker const std::vector<int> v = {1, 2, 3}; 73*6777b538SAndroid Build Coastguard Worker span<int> span(v); // expected-error {{no matching constructor for initialization of 'span<int>'}} 74*6777b538SAndroid Build Coastguard Worker} 75*6777b538SAndroid Build Coastguard Worker 76*6777b538SAndroid Build Coastguard Worker// A dynamic const container should not be implicitly convertible to a static span. 77*6777b538SAndroid Build Coastguard Workervoid ImplicitConversionFromDynamicConstContainerToStaticSpanDisallowed() { 78*6777b538SAndroid Build Coastguard Worker const std::vector<int> v = {1, 2, 3}; 79*6777b538SAndroid Build Coastguard Worker span<const int, 3u> span = v; // expected-error {{no viable conversion from 'const std::vector<int>' to 'span<const int, 3U>'}} 80*6777b538SAndroid Build Coastguard Worker} 81*6777b538SAndroid Build Coastguard Worker 82*6777b538SAndroid Build Coastguard Worker// A dynamic mutable container should not be implicitly convertible to a static span. 83*6777b538SAndroid Build Coastguard Workervoid ImplicitConversionFromDynamicMutableContainerToStaticSpanDisallowed() { 84*6777b538SAndroid Build Coastguard Worker std::vector<int> v = {1, 2, 3}; 85*6777b538SAndroid Build Coastguard Worker span<int, 3u> span = v; // expected-error {{no viable conversion from 'std::vector<int>' to 'span<int, 3U>'}} 86*6777b538SAndroid Build Coastguard Worker} 87*6777b538SAndroid Build Coastguard Worker 88*6777b538SAndroid Build Coastguard Worker// A std::set() should not satisfy the requirements for conversion to a span. 89*6777b538SAndroid Build Coastguard Workervoid StdSetConversionDisallowed() { 90*6777b538SAndroid Build Coastguard Worker std::set<int> set; 91*6777b538SAndroid Build Coastguard Worker span<int> span1(set.begin(), 0u); // expected-error {{no matching constructor for initialization of 'span<int>'}} 92*6777b538SAndroid Build Coastguard Worker span<int> span2(set.begin(), set.end()); // expected-error {{no matching constructor for initialization of 'span<int>'}} 93*6777b538SAndroid Build Coastguard Worker span<int> span3(set); // expected-error {{no matching constructor for initialization of 'span<int>'}} 94*6777b538SAndroid Build Coastguard Worker auto span4 = make_span(set.begin(), 0u); // expected-error@*:* {{no matching constructor for initialization of 'span<T>' (aka 'span<const int>')}} 95*6777b538SAndroid Build Coastguard Worker auto span5 = make_span(set.begin(), set.end()); // expected-error@*:* {{no matching constructor for initialization of 'span<T>' (aka 'span<const int>')}} 96*6777b538SAndroid Build Coastguard Worker auto span6 = make_span(set); // expected-error@*:* {{no matching function for call to 'data'}} 97*6777b538SAndroid Build Coastguard Worker} 98*6777b538SAndroid Build Coastguard Worker 99*6777b538SAndroid Build Coastguard Worker// Static views of spans with static extent must not exceed the size. 100*6777b538SAndroid Build Coastguard Workervoid OutOfRangeSubviewsOnStaticSpan() { 101*6777b538SAndroid Build Coastguard Worker std::array<int, 3> array = {1, 2, 3}; 102*6777b538SAndroid Build Coastguard Worker span<int, 3u> span(array); 103*6777b538SAndroid Build Coastguard Worker auto first = span.first<4>(); // expected-error@*:* {{no matching member function for call to 'first'}} 104*6777b538SAndroid Build Coastguard Worker auto last = span.last<4>(); // expected-error@*:* {{no matching member function for call to 'last'}} 105*6777b538SAndroid Build Coastguard Worker auto subspan1 = span.subspan<4>(); // expected-error@*:* {{no matching member function for call to 'subspan'}} 106*6777b538SAndroid Build Coastguard Worker auto subspan2 = span.subspan<0, 4>(); // expected-error@*:* {{no matching member function for call to 'subspan'}} 107*6777b538SAndroid Build Coastguard Worker} 108*6777b538SAndroid Build Coastguard Worker 109*6777b538SAndroid Build Coastguard Worker// Discarding the return value of empty() is not allowed. 110*6777b538SAndroid Build Coastguard Workervoid DiscardReturnOfEmptyDisallowed() { 111*6777b538SAndroid Build Coastguard Worker span<int> s; 112*6777b538SAndroid Build Coastguard Worker s.empty(); // expected-error {{ignoring return value of function}} 113*6777b538SAndroid Build Coastguard Worker} 114*6777b538SAndroid Build Coastguard Worker 115*6777b538SAndroid Build Coastguard Worker// Getting elements of an empty span with static extent is not allowed. 116*6777b538SAndroid Build Coastguard Workervoid RefsOnEmptyStaticSpanDisallowed() { 117*6777b538SAndroid Build Coastguard Worker span<int, 0u> s; 118*6777b538SAndroid Build Coastguard Worker s.front(); // expected-error@*:* {{invalid reference to function 'front': constraints not satisfied}} 119*6777b538SAndroid Build Coastguard Worker s.back(); // expected-error@*:* {{invalid reference to function 'back': constraints not satisfied}} 120*6777b538SAndroid Build Coastguard Worker} 121*6777b538SAndroid Build Coastguard Worker 122*6777b538SAndroid Build Coastguard Worker// Calling swap on spans with different extents is not allowed. 123*6777b538SAndroid Build Coastguard Workervoid SwapWithDifferentExtentsDisallowed() { 124*6777b538SAndroid Build Coastguard Worker std::array<int, 3> array = {1, 2, 3}; 125*6777b538SAndroid Build Coastguard Worker span<int, 3u> static_span(array); 126*6777b538SAndroid Build Coastguard Worker span<int> dynamic_span(array); 127*6777b538SAndroid Build Coastguard Worker std::swap(static_span, dynamic_span); // expected-error {{no matching function for call to 'swap'}} 128*6777b538SAndroid Build Coastguard Worker} 129*6777b538SAndroid Build Coastguard Worker 130*6777b538SAndroid Build Coastguard Worker// as_writable_bytes should not be possible for a const container. 131*6777b538SAndroid Build Coastguard Workervoid AsWritableBytesWithConstContainerDisallowed() { 132*6777b538SAndroid Build Coastguard Worker const std::vector<int> v = {1, 2, 3}; 133*6777b538SAndroid Build Coastguard Worker span<uint8_t> bytes = as_writable_bytes(make_span(v)); // expected-error {{no matching function for call to 'as_writable_bytes'}} 134*6777b538SAndroid Build Coastguard Worker} 135*6777b538SAndroid Build Coastguard Worker 136*6777b538SAndroid Build Coastguard Workervoid ConstVectorDeducesAsConstSpan() { 137*6777b538SAndroid Build Coastguard Worker const std::vector<int> v; 138*6777b538SAndroid Build Coastguard Worker span<int> s = make_span(v); // expected-error-re@*:* {{no viable conversion from 'span<{{.*}}, [...]>' to 'span<int, [...]>'}} 139*6777b538SAndroid Build Coastguard Worker} 140*6777b538SAndroid Build Coastguard Worker 141*6777b538SAndroid Build Coastguard Worker// make_span<N>() should CHECK whether N matches the actual size. 142*6777b538SAndroid Build Coastguard Workervoid MakeSpanChecksSize() { 143*6777b538SAndroid Build Coastguard Worker constexpr std::string_view str = "Foo"; 144*6777b538SAndroid Build Coastguard Worker constexpr auto made_span1 = make_span<2>(str.begin(), 3u); // expected-error {{constexpr variable 'made_span1' must be initialized by a constant expression}} 145*6777b538SAndroid Build Coastguard Worker constexpr auto made_span2 = make_span<2>(str.begin(), str.end()); // expected-error {{constexpr variable 'made_span2' must be initialized by a constant expression}} 146*6777b538SAndroid Build Coastguard Worker constexpr auto made_span3 = make_span<2>(str); // expected-error {{constexpr variable 'made_span3' must be initialized by a constant expression}} 147*6777b538SAndroid Build Coastguard Worker} 148*6777b538SAndroid Build Coastguard Worker 149*6777b538SAndroid Build Coastguard Worker// EXTENT should not result in |dynamic_extent|, it should be a compile-time 150*6777b538SAndroid Build Coastguard Worker// error. 151*6777b538SAndroid Build Coastguard Workervoid ExtentNoDynamicExtent() { 152*6777b538SAndroid Build Coastguard Worker std::vector<uint8_t> vector; 153*6777b538SAndroid Build Coastguard Worker constexpr size_t extent = EXTENT(vector); // expected-error@*:* {{EXTENT should only be used for containers with a static extent}} 154*6777b538SAndroid Build Coastguard Worker} 155*6777b538SAndroid Build Coastguard Worker 156*6777b538SAndroid Build Coastguard Workervoid Dangling() { 157*6777b538SAndroid Build Coastguard Worker span<const int, 3u> s1{std::array<int, 3>()}; // expected-error {{object backing the pointer will be destroyed at the end of the full-expression}} 158*6777b538SAndroid Build Coastguard Worker span<const int> s2{std::vector<int>({1, 2, 3})}; // expected-error {{object backing the pointer will be destroyed at the end of the full-expression}} 159*6777b538SAndroid Build Coastguard Worker} 160*6777b538SAndroid Build Coastguard Worker 161*6777b538SAndroid Build Coastguard Workervoid NotSizeTSize() { 162*6777b538SAndroid Build Coastguard Worker std::vector<int> vector = {1, 2, 3}; 163*6777b538SAndroid Build Coastguard Worker // Using distinct enum types causes distinct span template instantiations, so 164*6777b538SAndroid Build Coastguard Worker // we get assertion failures below where we expect. 165*6777b538SAndroid Build Coastguard Worker enum Length1 { kSize1 = -1 }; 166*6777b538SAndroid Build Coastguard Worker enum Length2 { kSize2 = -1 }; 167*6777b538SAndroid Build Coastguard Worker auto s1 = make_span(vector.data(), kSize1); // expected-error@*:* {{The source type is out of range for the destination type}} 168*6777b538SAndroid Build Coastguard Worker span s2(vector.data(), kSize2); // expected-error@*:* {{The source type is out of range for the destination type}} 169*6777b538SAndroid Build Coastguard Worker} 170*6777b538SAndroid Build Coastguard Worker 171*6777b538SAndroid Build Coastguard Workervoid BadConstConversionsWithStdSpan() { 172*6777b538SAndroid Build Coastguard Worker int kData[] = {10, 11, 12}; 173*6777b538SAndroid Build Coastguard Worker { 174*6777b538SAndroid Build Coastguard Worker base::span<const int, 3u> fixed_base_span(kData); 175*6777b538SAndroid Build Coastguard Worker std::span<int, 3u> s(fixed_base_span); // expected-error {{no matching constructor}} 176*6777b538SAndroid Build Coastguard Worker } 177*6777b538SAndroid Build Coastguard Worker { 178*6777b538SAndroid Build Coastguard Worker std::span<const int, 3u> fixed_std_span(kData); 179*6777b538SAndroid Build Coastguard Worker base::span<int, 3u> s(fixed_std_span); // expected-error {{no matching constructor}} 180*6777b538SAndroid Build Coastguard Worker } 181*6777b538SAndroid Build Coastguard Worker} 182*6777b538SAndroid Build Coastguard Worker 183*6777b538SAndroid Build Coastguard Workervoid FromVolatileArrayDisallowed() { 184*6777b538SAndroid Build Coastguard Worker static volatile int array[] = {1, 2, 3}; 185*6777b538SAndroid Build Coastguard Worker span<int> s(array); // expected-error {{no matching constructor for initialization of 'span<int>'}} 186*6777b538SAndroid Build Coastguard Worker} 187*6777b538SAndroid Build Coastguard Worker 188*6777b538SAndroid Build Coastguard Workervoid FixedSizeCopyTooSmall() { 189*6777b538SAndroid Build Coastguard Worker const int src[] = {1, 2, 3}; 190*6777b538SAndroid Build Coastguard Worker int dst[2]; 191*6777b538SAndroid Build Coastguard Worker base::span(dst).copy_from(base::make_span(src)); // expected-error@*:* {{no viable conversion}} 192*6777b538SAndroid Build Coastguard Worker 193*6777b538SAndroid Build Coastguard Worker base::span(dst).copy_from(src); // expected-error@*:* {{no viable conversion}} 194*6777b538SAndroid Build Coastguard Worker} 195*6777b538SAndroid Build Coastguard Worker 196*6777b538SAndroid Build Coastguard Workervoid FixedSizeSplitAtOutOfBounds() { 197*6777b538SAndroid Build Coastguard Worker const int arr[] = {1, 2, 3}; 198*6777b538SAndroid Build Coastguard Worker base::span(arr).split_at<4u>(); // expected-error@*:* {{no matching member function for call to 'split_at'}} 199*6777b538SAndroid Build Coastguard Worker} 200*6777b538SAndroid Build Coastguard Worker 201*6777b538SAndroid Build Coastguard Workervoid FromRefNoSuchFunctionForIntLiteral() { 202*6777b538SAndroid Build Coastguard Worker // Expectations of this test just capture the current behavior which is not 203*6777b538SAndroid Build Coastguard Worker // necessarily desirable or required. This test expects that when we ask the 204*6777b538SAndroid Build Coastguard Worker // compiler to deduce the template arguments for `span_from_ref` (the only 205*6777b538SAndroid Build Coastguard Worker // difference from `FromRefLifetimeBoundErrorForIntLiteral` below) then it 206*6777b538SAndroid Build Coastguard Worker // will fail to find a suitable function to invoke. 207*6777b538SAndroid Build Coastguard Worker auto wont_work = span_from_ref(123); // expected-error@*:* {{no matching function for call to 'span_from_ref'}} 208*6777b538SAndroid Build Coastguard Worker} 209*6777b538SAndroid Build Coastguard Worker 210*6777b538SAndroid Build Coastguard Workervoid FromRefLifetimeBoundErrorForIntLiteral() { 211*6777b538SAndroid Build Coastguard Worker // Testing that `ABSL_ATTRIBUTE_LIFETIME_BOUND` works as intended. 212*6777b538SAndroid Build Coastguard Worker [[maybe_unused]] auto wont_work = 213*6777b538SAndroid Build Coastguard Worker span_from_ref<const int>(123); // expected-error@*:* {{temporary whose address is used as value of local variable 'wont_work' will be destroyed at the end of the full-expression}} 214*6777b538SAndroid Build Coastguard Worker} 215*6777b538SAndroid Build Coastguard Worker 216*6777b538SAndroid Build Coastguard Workervoid FromRefLifetimeBoundErrorForTemporaryStringObject() { 217*6777b538SAndroid Build Coastguard Worker // Testing that `ABSL_ATTRIBUTE_LIFETIME_BOUND` works as intended. 218*6777b538SAndroid Build Coastguard Worker [[maybe_unused]] auto wont_work = 219*6777b538SAndroid Build Coastguard Worker span_from_ref<const std::string>("temporary string"); // expected-error@*:* {{temporary whose address is used as value of local variable 'wont_work' will be destroyed at the end of the full-expression}} 220*6777b538SAndroid Build Coastguard Worker} 221*6777b538SAndroid Build Coastguard Worker 222*6777b538SAndroid Build Coastguard Workervoid RvalueArrayLifetime() { 223*6777b538SAndroid Build Coastguard Worker [[maybe_unused]] auto wont_work = 224*6777b538SAndroid Build Coastguard Worker as_byte_span({1, 2}); // expected-error@*:* {{temporary whose address is used as value of local variable 'wont_work' will be destroyed at the end of the full-expression}} 225*6777b538SAndroid Build Coastguard Worker} 226*6777b538SAndroid Build Coastguard Worker 227*6777b538SAndroid Build Coastguard Workervoid FromCStringThatIsntStaticLifetime() { 228*6777b538SAndroid Build Coastguard Worker [[maybe_unused]] auto wont_work = 229*6777b538SAndroid Build Coastguard Worker span_from_cstring({'a', 'b', '\0'}); // expected-error@*:* {{temporary whose address is used as value of local variable 'wont_work' will be destroyed at the end of the full-expression}} 230*6777b538SAndroid Build Coastguard Worker 231*6777b538SAndroid Build Coastguard Worker [[maybe_unused]] auto wont_work2 = 232*6777b538SAndroid Build Coastguard Worker byte_span_from_cstring({'a', 'b', '\0'}); // expected-error@*:* {{temporary whose address is used as value of local variable 'wont_work2' will be destroyed at the end of the full-expression}} 233*6777b538SAndroid Build Coastguard Worker} 234*6777b538SAndroid Build Coastguard Worker 235*6777b538SAndroid Build Coastguard Workervoid CompareFixedSizeMismatch() { 236*6777b538SAndroid Build Coastguard Worker const int arr[] = {1, 2, 3}; 237*6777b538SAndroid Build Coastguard Worker const int arr2[] = {1, 2, 3, 4}; 238*6777b538SAndroid Build Coastguard Worker (void)(span(arr) == arr2); // expected-error@*:* {{invalid operands to binary expression}} 239*6777b538SAndroid Build Coastguard Worker (void)(span(arr) == span(arr2)); // expected-error@*:* {{invalid operands to binary expression}} 240*6777b538SAndroid Build Coastguard Worker} 241*6777b538SAndroid Build Coastguard Worker 242*6777b538SAndroid Build Coastguard Workervoid CompareNotComparable() { 243*6777b538SAndroid Build Coastguard Worker struct NoEq { int i; }; 244*6777b538SAndroid Build Coastguard Worker static_assert(!std::equality_comparable<NoEq>); 245*6777b538SAndroid Build Coastguard Worker 246*6777b538SAndroid Build Coastguard Worker const NoEq arr[] = {{1}, {2}, {3}}; 247*6777b538SAndroid Build Coastguard Worker (void)(span(arr) == arr); // expected-error@*:* {{invalid operands to binary expression}} 248*6777b538SAndroid Build Coastguard Worker (void)(span(arr) == span(arr)); // expected-error@*:* {{invalid operands to binary expression}} 249*6777b538SAndroid Build Coastguard Worker 250*6777b538SAndroid Build Coastguard Worker struct SelfEq { 251*6777b538SAndroid Build Coastguard Worker constexpr bool operator==(SelfEq s) const { return i == s.i; } 252*6777b538SAndroid Build Coastguard Worker int i; 253*6777b538SAndroid Build Coastguard Worker }; 254*6777b538SAndroid Build Coastguard Worker static_assert(std::equality_comparable<SelfEq>); 255*6777b538SAndroid Build Coastguard Worker static_assert(!std::equality_comparable_with<SelfEq, int>); 256*6777b538SAndroid Build Coastguard Worker 257*6777b538SAndroid Build Coastguard Worker const SelfEq self_arr[] = {{1}, {2}, {3}}; 258*6777b538SAndroid Build Coastguard Worker const int int_arr[] = {1, 2, 3}; 259*6777b538SAndroid Build Coastguard Worker 260*6777b538SAndroid Build Coastguard Worker (void)(span(self_arr) == int_arr); // expected-error@*:* {{invalid operands to binary expression}} 261*6777b538SAndroid Build Coastguard Worker (void)(span(self_arr) == span(int_arr)); // expected-error@*:* {{invalid operands to binary expression}} 262*6777b538SAndroid Build Coastguard Worker 263*6777b538SAndroid Build Coastguard Worker // Span's operator== works on `const T` and thus won't be able to use the 264*6777b538SAndroid Build Coastguard Worker // non-const operator here. We get this from equality_comparable which also 265*6777b538SAndroid Build Coastguard Worker // requires it. 266*6777b538SAndroid Build Coastguard Worker struct NonConstEq { 267*6777b538SAndroid Build Coastguard Worker constexpr bool operator==(NonConstEq s) { return i == s.i; } 268*6777b538SAndroid Build Coastguard Worker int i; 269*6777b538SAndroid Build Coastguard Worker }; 270*6777b538SAndroid Build Coastguard Worker const NonConstEq non_arr[] = {{1}, {2}, {3}}; 271*6777b538SAndroid Build Coastguard Worker (void)(span(non_arr) == non_arr); // expected-error@*:* {{invalid operands to binary expression}} 272*6777b538SAndroid Build Coastguard Worker (void)(span(non_arr) == span(non_arr)); // expected-error@*:* {{invalid operands to binary expression}} 273*6777b538SAndroid Build Coastguard Worker} 274*6777b538SAndroid Build Coastguard Worker 275*6777b538SAndroid Build Coastguard Workervoid AsStringViewNotBytes() { 276*6777b538SAndroid Build Coastguard Worker const int arr[] = {1, 2, 3}; 277*6777b538SAndroid Build Coastguard Worker as_string_view(base::span(arr)); // expected-error@*:* {{no matching function for call to 'as_string_view'}} 278*6777b538SAndroid Build Coastguard Worker} 279*6777b538SAndroid Build Coastguard Worker 280*6777b538SAndroid Build Coastguard Worker} // namespace base 281