brintos

brintos / llvm-project-archived public Read only

0
0
Text · 10.5 KiB · 261dd6e Raw
273 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// <algorithm>10 11// UNSUPPORTED: c++03, c++11, c++14, c++17, c++2012 13// template<input_iterator I, sentinel_for<I> S, class T,14//          indirectly-binary-left-foldable<T, I> F>15//   constexpr see below ranges::fold_left_with_iter(I first, S last, T init, F f);16//17// template<input_range R, class T, indirectly-binary-left-foldable<T, iterator_t<R>> F>18//   constexpr see below ranges::fold_left_with_iter(R&& r, T init, F f);19 20// template<input_iterator I, sentinel_for<I> S, class T,21//          indirectly-binary-left-foldable<T, I> F>22//   constexpr see below ranges::fold_left(I first, S last, T init, F f);23//24// template<input_range R, class T, indirectly-binary-left-foldable<T, iterator_t<R>> F>25//   constexpr see below ranges::fold_left(R&& r, T init, F f);26 27// Checks that the algorithm requirements reject parameters that don't meet the overloads' constraints.28 29#include <algorithm>30#include <concepts>31#include <cstddef>32#include <functional>33#include <iterator>34#include <ranges>35 36#include "test_iterators.h"37 38// FIXME(cjdb): deduplicate39struct bad_iterator_category {40  using value_type        = int;41  using difference_type   = std::ptrdiff_t;42  using iterator_category = void;43 44  value_type operator*() const;45 46  bad_iterator_category& operator++();47  void operator++(int);48};49 50// Covers indirectly_readable<I> too51template <std::input_or_output_iterator T>52  requires(!std::input_iterator<T>)53void requires_input_iterator() {54  struct bad_range {55    T begin();56    std::unreachable_sentinel_t end();57  };58 59  static_assert(!requires(bad_range r) {60    std::ranges::fold_left_with_iter(r.begin(), r.end(), std::unreachable_sentinel, 0, std::plus());61  });62  static_assert(!requires(bad_range r) { std::ranges::fold_left_with_iter(r, 0, std::plus()); });63 64  static_assert(!requires(bad_range r) {65    std::ranges::fold_left(r.begin(), r.end(), std::unreachable_sentinel, 0, std::plus());66  });67 68  static_assert(!requires(bad_range r) { std::ranges::fold_left(r, 0, std::plus()); });69}70 71template <std::equality_comparable S>72  requires(!std::sentinel_for<int*, S>)73void requires_sentinel() {74  static_assert(!requires(S first, S last) { std::ranges::fold_left_with_iter(first, last, 0, std::plus()); });75  static_assert(!requires(S first, S last) { std::ranges::fold_left(first, last, 0, std::plus()); });76}77 78struct non_copy_constructible_callable {79  non_copy_constructible_callable(non_copy_constructible_callable&&)      = default;80  non_copy_constructible_callable(non_copy_constructible_callable const&) = delete;81 82  int operator()(int, int) const;83};84 85template <class F>86  requires(!std::copy_constructible<F>)87void requires_copy_constructible_F() {88  static_assert(!requires(std::ranges::subrange<int*, int*> r, F f) {89    std::ranges::fold_left_with_iter(r.begin(), r.end(), 0, std::move(f));90  });91  static_assert(!requires(std::ranges::subrange<int*, int*> r, F f) {92    std::ranges::fold_left_with_iter(r, 0, std::move(f));93  });94 95  static_assert(!requires(std::ranges::subrange<int*, int*> r, F f) {96    std::ranges::fold_left(r.begin(), r.end(), 0, std::move(f));97  });98  static_assert(!requires(std::ranges::subrange<int*, int*> r, F f) { std::ranges::fold_left(r, 0, std::move(f)); });99}100 101struct not_invocable_with_lvalue_rhs {102  int operator()(int, int&&);103};104 105template <class F>106  requires(!std::invocable<F&, int, std::iter_reference_t<int*>>)107void requires_raw_invocable() {108  static_assert(!requires(std::ranges::subrange<int*, int*> r, F f) {109    std::ranges::fold_left_with_iter(r.begin(), r.end(), 0, f);110  });111  static_assert(!requires(std::ranges::subrange<int*, int*> r, F f) { std::ranges::fold_left_with_iter(r, 0, f); });112 113  static_assert(!requires(std::ranges::subrange<int*, int*> r, F f) {114    std::ranges::fold_left(r.begin(), r.end(), 0, f);115  });116  static_assert(!requires(std::ranges::subrange<int*, int*> r, F f) { std::ranges::fold_left(r, 0, f); });117}118 119struct S {};120 121struct non_decayable_result {122  S volatile& operator()(S, S) const;123};124 125template <std::invocable<S, std::iter_reference_t<S*>> F>126  requires(!std::convertible_to<std::invoke_result_t<F&, S, std::iter_reference_t<S*>>,127                                std::decay_t<std::invoke_result_t<F&, S, std::iter_reference_t<S*>>>>)128void requires_decaying_invoke_result() {129  static_assert(!requires(std::ranges::subrange<S*, S*> r, S init, F f) {130    std::ranges::fold_left_with_iter(r.begin(), r.end(), init, f);131  });132  static_assert(!requires(std::ranges::subrange<S*, S*> r, S init, F f) {133    std::ranges::fold_left_with_iter(r, init, f);134  });135 136  static_assert(!requires(std::ranges::subrange<S*, S*> r, S init, F f) {137    std::ranges::fold_left(r.begin(), r.end(), init, f);138  });139  static_assert(!requires(std::ranges::subrange<S*, S*> r, S init, F f) { std::ranges::fold_left(r, init, f); });140}141 142struct non_movable {143  non_movable(int);144  non_movable(non_movable&&) = delete;145 146  int apply(non_movable const&) const;147};148 149template <class T>150  requires(!std::movable<T>)151void requires_movable_init() {152  static_assert(!requires(std::ranges::subrange<T*, T*> r, T init) {153    std::ranges::fold_left_with_iter(r.begin(), r.end(), init, &T::apply);154  });155  static_assert(!requires(std::ranges::subrange<T*, T*> r, T init) {156    std::ranges::fold_left_with_iter(r, init, &T::apply);157  });158  static_assert(!requires(std::ranges::subrange<T*, T*> r, T init) {159    std::ranges::fold_left(r.begin(), r.end(), init, &T::apply);160  });161  static_assert(!requires(std::ranges::subrange<T*, T*> r, T init) { std::ranges::fold_left(r, init, &T::apply); });162}163 164struct result_not_movable_after_decay {165  result_not_movable_after_decay(int);166  result_not_movable_after_decay(result_not_movable_after_decay&&) = delete;167  result_not_movable_after_decay(result_not_movable_after_decay const&);168 169  friend result_not_movable_after_decay const& operator+(int, result_not_movable_after_decay const&);170  friend result_not_movable_after_decay const& operator+(result_not_movable_after_decay const&, int);171  friend result_not_movable_after_decay const&172  operator+(result_not_movable_after_decay const&, result_not_movable_after_decay const&);173};174 175template <class T>176  requires(!std::movable<T>)177void requires_movable_decayed() {178  static_assert(!requires(std::ranges::subrange<T*, T*> r) {179    std::ranges::fold_left_with_iter(r.begin(), r.end(), 0, std::plus());180  });181  static_assert(!requires(std::ranges::subrange<T*, T*> r) { std::ranges::fold_left_with_iter(r, 0, std::plus()); });182 183  static_assert(!requires(std::ranges::subrange<T*, T*> r) {184    std::ranges::fold_left(r.begin(), r.end(), 0, T::apply);185  });186  static_assert(!requires(std::ranges::subrange<T*, T*> r) { std::ranges::fold_left(r, 0, std::plus()); });187}188 189struct not_convertible_to_int {190  friend int operator+(not_convertible_to_int, not_convertible_to_int);191  friend int operator+(not_convertible_to_int, int);192  friend int operator+(int, not_convertible_to_int);193};194 195template <class T>196  requires(!std::convertible_to<T, int>)197void requires_init_is_convertible_to_decayed() {198  static_assert(!requires(std::ranges::subrange<int*, int*> r, T init) {199    std::ranges::fold_left_with_iter(r.begin(), r.end(), init, std::plus());200  });201  static_assert(!requires(std::ranges::subrange<int*, int*> r, T init) {202    std::ranges::fold_left_with_iter(r, init, std::plus());203  });204 205  static_assert(!requires(std::ranges::subrange<int*, int*> r, T init) {206    std::ranges::fold_left(r.begin(), r.end(), init, std::plus());207  });208  static_assert(!requires(std::ranges::subrange<int*, int*> r, T init) {209    std::ranges::fold_left(r, init, std::plus());210  });211}212 213struct not_invocable_with_decayed {214  not_invocable_with_decayed(int);215  friend not_invocable_with_decayed& operator+(int, not_invocable_with_decayed&);216  friend not_invocable_with_decayed& operator+(not_invocable_with_decayed&, int);217  friend not_invocable_with_decayed& operator+(not_invocable_with_decayed volatile&, not_invocable_with_decayed&);218};219 220template <class T>221  requires(!std::invocable<std::plus<>&, T, T&>)222void requires_invocable_with_decayed() {223  static_assert(!requires(std::ranges::subrange<T*, T*> r, int init) {224    std::ranges::fold_left_with_iter(r.begin(), r.end(), init, std::plus());225  });226  static_assert(!requires(std::ranges::subrange<T*, T*> r, int init) {227    std::ranges::fold_left_with_iter(r, init, std::plus());228  });229 230  static_assert(!requires(std::ranges::subrange<T*, T*> r, int init) {231    std::ranges::fold_left(r.begin(), r.end(), init, std::plus());232  });233  static_assert(!requires(std::ranges::subrange<T*, T*> r, int init) { std::ranges::fold_left(r, init, std::plus()); });234}235 236struct not_assignable_to_decayed {237  not_assignable_to_decayed();238  not_assignable_to_decayed(not_assignable_to_decayed&);239  not_assignable_to_decayed(not_assignable_to_decayed const&);240  not_assignable_to_decayed(not_assignable_to_decayed volatile&);241  not_assignable_to_decayed(not_assignable_to_decayed const volatile&);242  friend not_assignable_to_decayed volatile& operator+(not_assignable_to_decayed, not_assignable_to_decayed);243};244 245template <class T>246  requires(!std::assignable_from<T&, T volatile&>)247void requires_assignable_from_invoke_result() {248  static_assert(!requires(std::ranges::subrange<T*, T*> r, T init) {249    std::ranges::fold_left_with_iter(r.begin(), r.end(), init, std::plus());250  });251  static_assert(!requires(std::ranges::subrange<T*, T*> r, T init) {252    std::ranges::fold_left_with_iter(r, init, std::plus());253  });254 255  static_assert(!requires(std::ranges::subrange<T*, T*> r, T init) {256    std::ranges::fold_left(r.begin(), r.end(), init, std::plus());257  });258  static_assert(!requires(std::ranges::subrange<T*, T*> r, T init) { std::ranges::fold_left(r, init, std::plus()); });259}260 261void test() {262  requires_input_iterator<bad_iterator_category>();263  requires_sentinel<cpp17_input_iterator<int*>>();264  requires_copy_constructible_F<non_copy_constructible_callable>();265  requires_raw_invocable<not_invocable_with_lvalue_rhs>();266  requires_decaying_invoke_result<non_decayable_result>();267  requires_movable_init<non_movable>();268  requires_movable_decayed<result_not_movable_after_decay>();269  requires_init_is_convertible_to_decayed<not_convertible_to_int>();270  requires_invocable_with_decayed<not_invocable_with_decayed>();271  requires_assignable_from_invoke_result<not_assignable_to_decayed>();272}273