brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.7 KiB · 990b75b Raw
187 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// std::ranges::empty12 13#include <ranges>14 15#include <cassert>16#include <utility>17#include "test_macros.h"18#include "test_iterators.h"19 20using RangeEmptyT = decltype(std::ranges::empty);21 22static_assert(!std::is_invocable_v<RangeEmptyT, int[]>);23static_assert(!std::is_invocable_v<RangeEmptyT, int(&)[]>);24static_assert(!std::is_invocable_v<RangeEmptyT, int(&&)[]>);25static_assert( std::is_invocable_v<RangeEmptyT, int[1]>);26static_assert( std::is_invocable_v<RangeEmptyT, const int[1]>);27static_assert( std::is_invocable_v<RangeEmptyT, int (&&)[1]>);28static_assert( std::is_invocable_v<RangeEmptyT, int (&)[1]>);29static_assert( std::is_invocable_v<RangeEmptyT, const int (&)[1]>);30 31struct Incomplete;32static_assert(!std::is_invocable_v<RangeEmptyT, Incomplete[]>);33static_assert(!std::is_invocable_v<RangeEmptyT, Incomplete(&)[]>);34static_assert(!std::is_invocable_v<RangeEmptyT, Incomplete(&&)[]>);35 36extern Incomplete array_of_incomplete[42];37static_assert(!std::ranges::empty(array_of_incomplete));38static_assert(!std::ranges::empty(std::move(array_of_incomplete)));39static_assert(!std::ranges::empty(std::as_const(array_of_incomplete)));40static_assert(!std::ranges::empty(static_cast<const Incomplete(&&)[42]>(array_of_incomplete)));41 42struct InputRangeWithoutSize {43    cpp17_input_iterator<int*> begin() const;44    cpp17_input_iterator<int*> end() const;45};46static_assert(!std::is_invocable_v<RangeEmptyT, const InputRangeWithoutSize&>);47 48struct NonConstEmpty {49  bool empty();50};51static_assert(!std::is_invocable_v<RangeEmptyT, const NonConstEmpty&>);52 53struct HasMemberAndFunction {54  constexpr bool empty() const { return true; }55  // We should never do ADL lookup for std::ranges::empty.56  friend bool empty(const HasMemberAndFunction&) { return false; }57};58 59struct BadReturnType {60  BadReturnType empty() { return {}; }61};62static_assert(!std::is_invocable_v<RangeEmptyT, BadReturnType&>);63 64struct BoolConvertible {65  constexpr explicit operator bool() noexcept(false) { return true; }66};67struct BoolConvertibleReturnType {68  constexpr BoolConvertible empty() noexcept { return {}; }69};70static_assert(!noexcept(std::ranges::empty(BoolConvertibleReturnType())));71 72struct InputIterators {73  cpp17_input_iterator<int*> begin() const;74  cpp17_input_iterator<int*> end() const;75};76static_assert(std::is_same_v<decltype(InputIterators().begin() == InputIterators().end()), bool>);77static_assert(!std::is_invocable_v<RangeEmptyT, const InputIterators&>);78 79constexpr bool testEmptyMember() {80  HasMemberAndFunction a;81  assert(std::ranges::empty(a));82 83  BoolConvertibleReturnType b;84  assert(std::ranges::empty(b));85 86  return true;87}88 89struct SizeMember {90  std::size_t size_;91  constexpr std::size_t size() const { return size_; }92};93 94struct SizeFunction {95  std::size_t size_;96  friend constexpr std::size_t size(SizeFunction sf) { return sf.size_; }97};98 99struct BeginEndSizedSentinel {100  constexpr int *begin() const { return nullptr; }101  constexpr auto end() const { return sized_sentinel<int*>(nullptr); }102};103static_assert(std::ranges::forward_range<BeginEndSizedSentinel>);104static_assert(std::ranges::sized_range<BeginEndSizedSentinel>);105 106constexpr bool testUsingRangesSize() {107  SizeMember a{1};108  assert(!std::ranges::empty(a));109  SizeMember b{0};110  assert(std::ranges::empty(b));111 112  SizeFunction c{1};113  assert(!std::ranges::empty(c));114  SizeFunction d{0};115  assert(std::ranges::empty(d));116 117  BeginEndSizedSentinel e;118  assert(std::ranges::empty(e));119 120  return true;121}122 123struct BeginEndNotSizedSentinel {124  constexpr int *begin() const { return nullptr; }125  constexpr auto end() const { return sentinel_wrapper<int*>(nullptr); }126};127static_assert( std::ranges::forward_range<BeginEndNotSizedSentinel>);128static_assert(!std::ranges::sized_range<BeginEndNotSizedSentinel>);129 130// size is disabled here, so we have to compare begin and end.131struct DisabledSizeRangeWithBeginEnd {132  constexpr int *begin() const { return nullptr; }133  constexpr auto end() const { return sentinel_wrapper<int*>(nullptr); }134  std::size_t size() const;135};136template<>137inline constexpr bool std::ranges::disable_sized_range<DisabledSizeRangeWithBeginEnd> = true;138static_assert(std::ranges::contiguous_range<DisabledSizeRangeWithBeginEnd>);139static_assert(!std::ranges::sized_range<DisabledSizeRangeWithBeginEnd>);140 141struct BeginEndAndEmpty {142  constexpr int *begin() const { return nullptr; }143  constexpr auto end() const { return sentinel_wrapper<int*>(nullptr); }144  constexpr bool empty() { return false; }145};146 147struct EvilBeginEnd {148  bool empty() &&;149  constexpr int *begin() & { return nullptr; }150  constexpr int *end() & { return nullptr; }151};152 153constexpr bool testBeginEqualsEnd() {154  BeginEndNotSizedSentinel a;155  assert(std::ranges::empty(a));156 157  DisabledSizeRangeWithBeginEnd d;158  assert(std::ranges::empty(d));159 160  BeginEndAndEmpty e;161  assert(!std::ranges::empty(e)); // e.empty()162  assert(std::ranges::empty(std::as_const(e))); // e.begin() == e.end()163 164  assert(std::ranges::empty(EvilBeginEnd()));165 166  return true;167}168 169// Test ADL-proofing.170struct Incomplete;171template<class T> struct Holder { T t; };172static_assert(!std::is_invocable_v<RangeEmptyT, Holder<Incomplete>*>);173static_assert(!std::is_invocable_v<RangeEmptyT, Holder<Incomplete>*&>);174 175int main(int, char**) {176  testEmptyMember();177  static_assert(testEmptyMember());178 179  testUsingRangesSize();180  static_assert(testUsingRangesSize());181 182  testBeginEqualsEnd();183  static_assert(testBeginEqualsEnd());184 185  return 0;186}187