brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.9 KiB · 697085a Raw
234 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++17, c++2010 11// <ranges>12 13// std::views::chunk_by14 15#include <ranges>16 17#include <algorithm>18#include <cassert>19#include <concepts>20#include <initializer_list>21#include <type_traits>22#include <utility>23 24#include "test_iterators.h"25#include "test_range.h"26 27struct Pred {28  constexpr bool operator()(int x, int y) const { return x != -y; }29};30 31struct NonCopyablePredicate : Pred {32  NonCopyablePredicate(NonCopyablePredicate const&) = delete;33};34 35struct Range : std::ranges::view_base {36  using Iterator = forward_iterator<int*>;37  using Sentinel = sentinel_wrapper<Iterator>;38  constexpr explicit Range(int* b, int* e) : begin_(b), end_(e) {}39  constexpr Iterator begin() const { return Iterator(begin_); }40  constexpr Sentinel end() const { return Sentinel(Iterator(end_)); }41 42private:43  int* begin_;44  int* end_;45};46 47template <typename View>48constexpr void compareViews(View v, std::initializer_list<std::initializer_list<int>> list) {49  auto b1 = v.begin();50  auto e1 = v.end();51  auto b2 = list.begin();52  auto e2 = list.end();53  for (; b1 != e1 && b2 != e2; ++b1, ++b2) {54    bool eq = std::ranges::equal(*b1, *b2, [](int x, int y) {55      assert(x == y);56      return true;57    });58    assert(eq);59  }60  assert(b1 == e1);61  assert(b2 == e2);62}63 64constexpr int absoluteValue(int x) { return x < 0 ? -x : x; }65 66template <class T>67constexpr const T&& asConstRvalue(T&& t) {68  return static_cast<T const&&>(t);69}70 71constexpr bool test() {72  int buff[] = {-4, -3, -2, -1, 1, 2, 3, 4};73 74  // Test range adaptor object75  {76    using RangeAdaptorObject = decltype(std::views::chunk_by);77    static_assert(std::is_const_v<RangeAdaptorObject>);78 79    // The type of a customization point object, ignoring cv-qualifiers, shall model semiregular80    static_assert(std::semiregular<std::remove_const<RangeAdaptorObject>>);81  }82 83  // Test `views::chunk_by(pred)(v)`84  {85    using Result = std::ranges::chunk_by_view<Range, Pred>;86    Range const range(buff, buff + 8);87    Pred pred;88 89    {90      // 'views::chunk_by(pred)' - &&91      std::same_as<Result> decltype(auto) result = std::views::chunk_by(pred)(range);92      compareViews(result, {{-4, -3, -2, -1}, {1, 2, 3, 4}});93    }94    {95      // 'views::chunk_by(pred)' - const&&96      std::same_as<Result> decltype(auto) result = asConstRvalue(std::views::chunk_by(pred))(range);97      compareViews(result, {{-4, -3, -2, -1}, {1, 2, 3, 4}});98    }99    {100      // 'views::chunk_by(pred)' - &101      auto partial                               = std::views::chunk_by(pred);102      std::same_as<Result> decltype(auto) result = partial(range);103      compareViews(result, {{-4, -3, -2, -1}, {1, 2, 3, 4}});104    }105    {106      // 'views::chunk_by(pred)' - const&107      auto const partial                         = std::views::chunk_by(pred);108      std::same_as<Result> decltype(auto) result = partial(range);109      compareViews(result, {{-4, -3, -2, -1}, {1, 2, 3, 4}});110    }111  }112 113  // Test `v | views::chunk_by(pred)`114  {115    using Result = std::ranges::chunk_by_view<Range, Pred>;116    Range const range(buff, buff + 8);117    Pred pred;118 119    {120      // 'views::chunk_by(pred)' - &&121      std::same_as<Result> decltype(auto) result = range | std::views::chunk_by(pred);122      compareViews(result, {{-4, -3, -2, -1}, {1, 2, 3, 4}});123    }124    {125      // 'views::chunk_by(pred)' - const&&126      std::same_as<Result> decltype(auto) result = range | asConstRvalue(std::views::chunk_by(pred));127      compareViews(result, {{-4, -3, -2, -1}, {1, 2, 3, 4}});128    }129    {130      // 'views::chunk_by(pred)' - &131      auto partial                               = std::views::chunk_by(pred);132      std::same_as<Result> decltype(auto) result = range | partial;133      compareViews(result, {{-4, -3, -2, -1}, {1, 2, 3, 4}});134    }135    {136      // 'views::chunk_by(pred)' - const&137      auto const partial                         = std::views::chunk_by(pred);138      std::same_as<Result> decltype(auto) result = range | partial;139      compareViews(result, {{-4, -3, -2, -1}, {1, 2, 3, 4}});140    }141  }142 143  // Test `views::chunk_by(v, pred)` range adaptor object144  {145    using Result = std::ranges::chunk_by_view<Range, Pred>;146    Range const range(buff, buff + 8);147    Pred pred;148 149    {150      // 'views::chunk_by' - &&151      auto range_adaptor                         = std::views::chunk_by;152      std::same_as<Result> decltype(auto) result = std::move(range_adaptor)(range, pred);153      compareViews(result, {{-4, -3, -2, -1}, {1, 2, 3, 4}});154    }155    {156      // 'views::chunk_by' - const&&157      auto const range_adaptor                   = std::views::chunk_by;158      std::same_as<Result> decltype(auto) result = std::move(range_adaptor)(range, pred);159      compareViews(result, {{-4, -3, -2, -1}, {1, 2, 3, 4}});160    }161    {162      // 'views::chunk_by' - &163      auto range_adaptor                         = std::views::chunk_by;164      std::same_as<Result> decltype(auto) result = range_adaptor(range, pred);165      compareViews(result, {{-4, -3, -2, -1}, {1, 2, 3, 4}});166    }167    {168      // 'views::chunk_by' - const&169      auto const range_adaptor                   = std::views::chunk_by;170      std::same_as<Result> decltype(auto) result = range_adaptor(range, pred);171      compareViews(result, {{-4, -3, -2, -1}, {1, 2, 3, 4}});172    }173  }174 175  // Test that one can call std::views::chunk_by with arbitrary stuff, as long as we176  // don't try to actually complete the call by passing it a range.177  //178  // That makes no sense and we can't do anything with the result, but it's valid.179  {180    int array[3]                  = {1, 2, 3};181    [[maybe_unused]] auto partial = std::views::chunk_by(std::move(array));182  }183 184  // Test `adaptor | views::chunk_by(pred)`185  {186    Range const range(buff, buff + 8);187 188    {189      auto pred1 = [](int i) { return absoluteValue(i) < 3; };190      Pred pred2;191      using Result = std::ranges::chunk_by_view<std::ranges::filter_view<Range, decltype(pred1)>, Pred>;192      std::same_as<Result> decltype(auto) result = range | std::views::filter(pred1) | std::views::chunk_by(pred2);193      compareViews(result, {{-2, -1}, {1, 2}});194    }195    {196      auto pred1 = [](int i) { return absoluteValue(i) < 3; };197      Pred pred2;198      using Result       = std::ranges::chunk_by_view<std::ranges::filter_view<Range, decltype(pred1)>, Pred>;199      auto const partial = std::views::filter(pred1) | std::views::chunk_by(pred2);200      std::same_as<Result> decltype(auto) result = range | partial;201      compareViews(result, {{-2, -1}, {1, 2}});202    }203  }204 205  // Test SFINAE friendliness206  {207    struct NotAView {};208    struct NotInvocable {};209 210    static_assert(!CanBePiped<Range, decltype(std::views::chunk_by)>);211    static_assert(CanBePiped<Range, decltype(std::views::chunk_by(Pred{}))>);212    static_assert(!CanBePiped<NotAView, decltype(std::views::chunk_by(Pred{}))>);213    static_assert(!CanBePiped<std::initializer_list<int>, decltype(std::views::chunk_by(Pred{}))>);214    static_assert(!CanBePiped<Range, decltype(std::views::chunk_by(NotInvocable{}))>);215 216    static_assert(!std::is_invocable_v<decltype(std::views::chunk_by)>);217    static_assert(!std::is_invocable_v<decltype(std::views::chunk_by), Pred, Range>);218    static_assert(std::is_invocable_v<decltype(std::views::chunk_by), Range, Pred>);219    static_assert(!std::is_invocable_v<decltype(std::views::chunk_by), Range, Pred, Pred>);220    static_assert(!std::is_invocable_v<decltype(std::views::chunk_by), NonCopyablePredicate>);221  }222 223  { static_assert(std::is_same_v<decltype(std::ranges::views::chunk_by), decltype(std::views::chunk_by)>); }224 225  return true;226}227 228int main(int, char**) {229  test();230  static_assert(test());231 232  return 0;233}234