brintos

brintos / llvm-project-archived public Read only

0
0
Text · 11.9 KiB · 5ca3d59 Raw
342 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::begin12// std::ranges::cbegin13 14#include <ranges>15 16#include <cassert>17#include <utility>18#include "test_macros.h"19#include "test_iterators.h"20 21using RangeBeginT = decltype(std::ranges::begin);22using RangeCBeginT = decltype(std::ranges::cbegin);23 24static int globalBuff[8];25 26static_assert(!std::is_invocable_v<RangeBeginT, int (&&)[10]>);27static_assert( std::is_invocable_v<RangeBeginT, int (&)[10]>);28static_assert(!std::is_invocable_v<RangeBeginT, int (&&)[]>);29static_assert( std::is_invocable_v<RangeBeginT, int (&)[]>);30static_assert(!std::is_invocable_v<RangeCBeginT, int (&&)[10]>);31static_assert( std::is_invocable_v<RangeCBeginT, int (&)[10]>);32static_assert(!std::is_invocable_v<RangeCBeginT, int (&&)[]>);33static_assert( std::is_invocable_v<RangeCBeginT, int (&)[]>);34 35struct Incomplete;36static_assert(!std::is_invocable_v<RangeBeginT, Incomplete(&&)[]>);37static_assert(!std::is_invocable_v<RangeBeginT, const Incomplete(&&)[]>);38static_assert(!std::is_invocable_v<RangeCBeginT, Incomplete(&&)[]>);39static_assert(!std::is_invocable_v<RangeCBeginT, const Incomplete(&&)[]>);40 41static_assert(!std::is_invocable_v<RangeBeginT, Incomplete(&&)[10]>);42static_assert(!std::is_invocable_v<RangeBeginT, const Incomplete(&&)[10]>);43static_assert(!std::is_invocable_v<RangeCBeginT, Incomplete(&&)[10]>);44static_assert(!std::is_invocable_v<RangeCBeginT, const Incomplete(&&)[10]>);45 46// This case is IFNDR; we handle it SFINAE-friendly.47LIBCPP_STATIC_ASSERT(!std::is_invocable_v<RangeBeginT, Incomplete(&)[]>);48LIBCPP_STATIC_ASSERT(!std::is_invocable_v<RangeBeginT, const Incomplete(&)[]>);49LIBCPP_STATIC_ASSERT(!std::is_invocable_v<RangeCBeginT, Incomplete(&)[]>);50LIBCPP_STATIC_ASSERT(!std::is_invocable_v<RangeCBeginT, const Incomplete(&)[]>);51 52// This case is IFNDR; we handle it SFINAE-friendly.53LIBCPP_STATIC_ASSERT(!std::is_invocable_v<RangeBeginT, Incomplete(&)[10]>);54LIBCPP_STATIC_ASSERT(!std::is_invocable_v<RangeBeginT, const Incomplete(&)[10]>);55LIBCPP_STATIC_ASSERT(!std::is_invocable_v<RangeCBeginT, Incomplete(&)[10]>);56LIBCPP_STATIC_ASSERT(!std::is_invocable_v<RangeCBeginT, const Incomplete(&)[10]>);57 58struct BeginMember {59  int x;60  constexpr const int *begin() const { return &x; }61};62 63// Ensure that we can't call with rvalues with borrowing disabled.64static_assert( std::is_invocable_v<RangeBeginT, BeginMember &>);65static_assert(!std::is_invocable_v<RangeBeginT, BeginMember &&>);66static_assert( std::is_invocable_v<RangeBeginT, BeginMember const&>);67static_assert(!std::is_invocable_v<RangeBeginT, BeginMember const&&>);68static_assert( std::is_invocable_v<RangeCBeginT, BeginMember &>);69static_assert(!std::is_invocable_v<RangeCBeginT, BeginMember &&>);70static_assert( std::is_invocable_v<RangeCBeginT, BeginMember const&>);71static_assert(!std::is_invocable_v<RangeCBeginT, BeginMember const&&>);72 73constexpr bool testReturnTypes() {74  {75    int *x[2];76    ASSERT_SAME_TYPE(decltype(std::ranges::begin(x)), int**);77    ASSERT_SAME_TYPE(decltype(std::ranges::cbegin(x)), int* const*);78  }79  {80    int x[2][2];81    ASSERT_SAME_TYPE(decltype(std::ranges::begin(x)), int(*)[2]);82    ASSERT_SAME_TYPE(decltype(std::ranges::cbegin(x)), const int(*)[2]);83  }84  {85    struct Different {86      char*& begin();87      short*& begin() const;88    } x;89    ASSERT_SAME_TYPE(decltype(std::ranges::begin(x)), char*);90    ASSERT_SAME_TYPE(decltype(std::ranges::cbegin(x)), short*);91  }92  return true;93}94 95constexpr bool testArray() {96  int a[2];97  assert(std::ranges::begin(a) == a);98  assert(std::ranges::cbegin(a) == a);99 100  int b[2][2];101  assert(std::ranges::begin(b) == b);102  assert(std::ranges::cbegin(b) == b);103 104  BeginMember c[2];105  assert(std::ranges::begin(c) == c);106  assert(std::ranges::cbegin(c) == c);107 108  return true;109}110 111struct BeginMemberReturnsInt {112  int begin() const;113};114static_assert(!std::is_invocable_v<RangeBeginT, BeginMemberReturnsInt const&>);115 116struct BeginMemberReturnsVoidPtr {117  const void *begin() const;118};119static_assert(!std::is_invocable_v<RangeBeginT, BeginMemberReturnsVoidPtr const&>);120 121struct EmptyBeginMember {122  struct iterator {};123  iterator begin() const;124};125static_assert(!std::is_invocable_v<RangeBeginT, EmptyBeginMember const&>);126 127struct PtrConvertibleBeginMember {128  struct iterator { operator int*() const; };129  iterator begin() const;130};131static_assert(!std::is_invocable_v<RangeBeginT, PtrConvertibleBeginMember const&>);132 133struct NonConstBeginMember {134  int x;135  constexpr int *begin() { return &x; }136};137static_assert( std::is_invocable_v<RangeBeginT,  NonConstBeginMember &>);138static_assert(!std::is_invocable_v<RangeBeginT,  NonConstBeginMember const&>);139static_assert(!std::is_invocable_v<RangeCBeginT, NonConstBeginMember &>);140static_assert(!std::is_invocable_v<RangeCBeginT, NonConstBeginMember const&>);141 142struct EnabledBorrowingBeginMember {143  constexpr int *begin() const { return &globalBuff[0]; }144};145template<>146inline constexpr bool std::ranges::enable_borrowed_range<EnabledBorrowingBeginMember> = true;147 148struct BeginMemberFunction {149  int x;150  constexpr const int *begin() const { return &x; }151  friend int *begin(BeginMemberFunction const&);152};153 154struct EmptyPtrBeginMember {155  struct Empty {};156  Empty x;157  constexpr const Empty *begin() const { return &x; }158};159 160constexpr bool testBeginMember() {161  BeginMember a;162  assert(std::ranges::begin(a) == &a.x);163  assert(std::ranges::cbegin(a) == &a.x);164  static_assert(!std::is_invocable_v<RangeBeginT, BeginMember&&>);165  static_assert(!std::is_invocable_v<RangeCBeginT, BeginMember&&>);166 167  NonConstBeginMember b;168  assert(std::ranges::begin(b) == &b.x);169  static_assert(!std::is_invocable_v<RangeCBeginT, NonConstBeginMember&>);170 171  EnabledBorrowingBeginMember c;172  assert(std::ranges::begin(c) == &globalBuff[0]);173  assert(std::ranges::cbegin(c) == &globalBuff[0]);174  assert(std::ranges::begin(std::move(c)) == &globalBuff[0]);175  assert(std::ranges::cbegin(std::move(c)) == &globalBuff[0]);176 177  BeginMemberFunction d;178  assert(std::ranges::begin(d) == &d.x);179  assert(std::ranges::cbegin(d) == &d.x);180 181  EmptyPtrBeginMember e;182  assert(std::ranges::begin(e) == &e.x);183  assert(std::ranges::cbegin(e) == &e.x);184 185  return true;186}187 188 189struct BeginFunction {190  int x;191  friend constexpr const int *begin(BeginFunction const& bf) { return &bf.x; }192};193static_assert( std::is_invocable_v<RangeBeginT,  BeginFunction const&>);194static_assert(!std::is_invocable_v<RangeBeginT,  BeginFunction &&>);195static_assert(std::is_invocable_v<RangeBeginT, BeginFunction&>); // Ill-formed before P2602R2 Poison Pills are Too Toxic196static_assert( std::is_invocable_v<RangeCBeginT, BeginFunction const&>);197static_assert( std::is_invocable_v<RangeCBeginT, BeginFunction &>);198 199struct BeginFunctionReturnsInt {200  friend int begin(BeginFunctionReturnsInt const&);201};202static_assert(!std::is_invocable_v<RangeBeginT, BeginFunctionReturnsInt const&>);203 204struct BeginFunctionReturnsVoidPtr {205  friend void *begin(BeginFunctionReturnsVoidPtr const&);206};207static_assert(!std::is_invocable_v<RangeBeginT, BeginFunctionReturnsVoidPtr const&>);208 209struct BeginFunctionReturnsPtrConvertible {210  struct iterator { operator int*() const; };211  friend iterator begin(BeginFunctionReturnsPtrConvertible const&);212};213static_assert(!std::is_invocable_v<RangeBeginT, BeginFunctionReturnsPtrConvertible const&>);214 215struct BeginFunctionByValue {216  friend constexpr int *begin(BeginFunctionByValue) { return &globalBuff[1]; }217};218static_assert(!std::is_invocable_v<RangeCBeginT, BeginFunctionByValue>);219 220struct BeginFunctionEnabledBorrowing {221  friend constexpr int *begin(BeginFunctionEnabledBorrowing) { return &globalBuff[2]; }222};223template<>224inline constexpr bool std::ranges::enable_borrowed_range<BeginFunctionEnabledBorrowing> = true;225 226struct BeginFunctionReturnsEmptyPtr {227  struct Empty {};228  Empty x;229  friend constexpr const Empty *begin(BeginFunctionReturnsEmptyPtr const& bf) { return &bf.x; }230};231 232struct BeginFunctionWithDataMember {233  int x;234  int begin;235  friend constexpr const int *begin(BeginFunctionWithDataMember const& bf) { return &bf.x; }236};237 238struct BeginFunctionWithPrivateBeginMember {239  int y;240  friend constexpr const int *begin(BeginFunctionWithPrivateBeginMember const& bf) { return &bf.y; }241private:242  const int *begin() const;243};244 245constexpr bool testBeginFunction() {246  BeginFunction a{};247  const BeginFunction aa{};248  assert(std::ranges::begin(a) == &a.x); // Ill-formed before P2602R2 Poison Pills are Too Toxic249  assert(std::ranges::cbegin(a) == &a.x);250  assert(std::ranges::begin(aa) == &aa.x);251  assert(std::ranges::cbegin(aa) == &aa.x);252 253  BeginFunctionByValue b{};254  const BeginFunctionByValue bb{};255  assert(std::ranges::begin(b) == &globalBuff[1]);256  assert(std::ranges::cbegin(b) == &globalBuff[1]);257  assert(std::ranges::begin(bb) == &globalBuff[1]);258  assert(std::ranges::cbegin(bb) == &globalBuff[1]);259 260  BeginFunctionEnabledBorrowing c{};261  const BeginFunctionEnabledBorrowing cc{};262  assert(std::ranges::begin(std::move(c)) == &globalBuff[2]);263  assert(std::ranges::cbegin(std::move(c)) == &globalBuff[2]);264  assert(std::ranges::begin(std::move(cc)) == &globalBuff[2]);265  assert(std::ranges::cbegin(std::move(cc)) == &globalBuff[2]);266 267  BeginFunctionReturnsEmptyPtr d{};268  const BeginFunctionReturnsEmptyPtr dd{};269  assert(std::ranges::begin(d) == &d.x); // Ill-formed before P2602R2 Poison Pills are Too Toxic270  assert(std::ranges::cbegin(d) == &d.x);271  assert(std::ranges::begin(dd) == &dd.x);272  assert(std::ranges::cbegin(dd) == &dd.x);273 274  BeginFunctionWithDataMember e{};275  const BeginFunctionWithDataMember ee{};276  assert(std::ranges::begin(e) == &e.x); // Ill-formed before P2602R2 Poison Pills are Too Toxic277  assert(std::ranges::begin(ee) == &ee.x);278  assert(std::ranges::cbegin(e) == &e.x);279  assert(std::ranges::cbegin(ee) == &ee.x);280 281  BeginFunctionWithPrivateBeginMember f{};282  const BeginFunctionWithPrivateBeginMember ff{};283  assert(std::ranges::begin(f) == &f.y); // Ill-formed before P2602R2 Poison Pills are Too Toxic284  assert(std::ranges::cbegin(f) == &f.y);285  assert(std::ranges::begin(ff) == &ff.y);286  assert(std::ranges::cbegin(ff) == &ff.y);287 288  return true;289}290 291 292ASSERT_NOEXCEPT(std::ranges::begin(std::declval<int (&)[10]>()));293ASSERT_NOEXCEPT(std::ranges::cbegin(std::declval<int (&)[10]>()));294 295struct NoThrowMemberBegin {296  ThrowingIterator<int> begin() const noexcept; // auto(t.begin()) doesn't throw297} ntmb;298static_assert(noexcept(std::ranges::begin(ntmb)));299static_assert(noexcept(std::ranges::cbegin(ntmb)));300 301struct NoThrowADLBegin {302  friend ThrowingIterator<int> begin(NoThrowADLBegin&) noexcept;  // auto(begin(t)) doesn't throw303  friend ThrowingIterator<int> begin(const NoThrowADLBegin&) noexcept;304} ntab;305static_assert(noexcept(std::ranges::begin(ntab)));306static_assert(noexcept(std::ranges::cbegin(ntab)));307 308struct NoThrowMemberBeginReturnsRef {309  ThrowingIterator<int>& begin() const noexcept; // auto(t.begin()) may throw310} ntmbrr;311static_assert(!noexcept(std::ranges::begin(ntmbrr)));312static_assert(!noexcept(std::ranges::cbegin(ntmbrr)));313 314struct BeginReturnsArrayRef {315    auto begin() const noexcept -> int(&)[10];316} brar;317static_assert(noexcept(std::ranges::begin(brar)));318static_assert(noexcept(std::ranges::cbegin(brar)));319 320// Test ADL-proofing.321struct Incomplete;322template<class T> struct Holder { T t; };323static_assert(!std::is_invocable_v<RangeBeginT, Holder<Incomplete>*>);324static_assert(!std::is_invocable_v<RangeBeginT, Holder<Incomplete>*&>);325static_assert(!std::is_invocable_v<RangeCBeginT, Holder<Incomplete>*>);326static_assert(!std::is_invocable_v<RangeCBeginT, Holder<Incomplete>*&>);327 328int main(int, char**) {329  static_assert(testReturnTypes());330 331  testArray();332  static_assert(testArray());333 334  testBeginMember();335  static_assert(testBeginMember());336 337  testBeginFunction();338  static_assert(testBeginFunction());339 340  return 0;341}342