xref: /llvm-project/libcxx/test/std/algorithms/alg.nonmodifying/alg.fold/requirements.compile.pass.cpp (revision f0ea888e01aabcb131a8931b9e1fe1c5212a6cba)
139034388SChristopher Di Bella //===----------------------------------------------------------------------===//
239034388SChristopher Di Bella //
339034388SChristopher Di Bella // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
439034388SChristopher Di Bella // See https://llvm.org/LICENSE.txt for license information.
539034388SChristopher Di Bella // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
639034388SChristopher Di Bella //
739034388SChristopher Di Bella //===----------------------------------------------------------------------===//
839034388SChristopher Di Bella 
939034388SChristopher Di Bella // <algorithm>
1039034388SChristopher Di Bella 
1139034388SChristopher Di Bella // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
1239034388SChristopher Di Bella 
13*f0ea888eSChristopher Di Bella // template<input_iterator I, sentinel_for<I> S, class T,
14*f0ea888eSChristopher Di Bella //          indirectly-binary-left-foldable<T, I> F>
15*f0ea888eSChristopher Di Bella //   constexpr see below ranges::fold_left_with_iter(I first, S last, T init, F f);
16*f0ea888eSChristopher Di Bella //
17*f0ea888eSChristopher Di Bella // template<input_range R, class T, indirectly-binary-left-foldable<T, iterator_t<R>> F>
18*f0ea888eSChristopher Di Bella //   constexpr see below ranges::fold_left_with_iter(R&& r, T init, F f);
19*f0ea888eSChristopher Di Bella 
20*f0ea888eSChristopher Di Bella // template<input_iterator I, sentinel_for<I> S, class T,
21*f0ea888eSChristopher Di Bella //          indirectly-binary-left-foldable<T, I> F>
22*f0ea888eSChristopher Di Bella //   constexpr see below ranges::fold_left(I first, S last, T init, F f);
23*f0ea888eSChristopher Di Bella //
24*f0ea888eSChristopher Di Bella // template<input_range R, class T, indirectly-binary-left-foldable<T, iterator_t<R>> F>
25*f0ea888eSChristopher Di Bella //   constexpr see below ranges::fold_left(R&& r, T init, F f);
26*f0ea888eSChristopher Di Bella 
27*f0ea888eSChristopher Di Bella // Checks that the algorithm requirements reject parameters that don't meet the overloads' constraints.
2839034388SChristopher Di Bella 
2939034388SChristopher Di Bella #include <algorithm>
3039034388SChristopher Di Bella #include <concepts>
3139034388SChristopher Di Bella #include <cstddef>
3239034388SChristopher Di Bella #include <functional>
3339034388SChristopher Di Bella #include <iterator>
3439034388SChristopher Di Bella #include <ranges>
3539034388SChristopher Di Bella 
3639034388SChristopher Di Bella #include "test_iterators.h"
3739034388SChristopher Di Bella 
3839034388SChristopher Di Bella // FIXME(cjdb): deduplicate
3939034388SChristopher Di Bella struct bad_iterator_category {
4039034388SChristopher Di Bella   using value_type        = int;
4139034388SChristopher Di Bella   using difference_type   = std::ptrdiff_t;
4239034388SChristopher Di Bella   using iterator_category = void;
4339034388SChristopher Di Bella 
4439034388SChristopher Di Bella   value_type operator*() const;
4539034388SChristopher Di Bella 
4639034388SChristopher Di Bella   bad_iterator_category& operator++();
4739034388SChristopher Di Bella   void operator++(int);
4839034388SChristopher Di Bella };
4939034388SChristopher Di Bella 
5039034388SChristopher Di Bella // Covers indirectly_readable<I> too
5139034388SChristopher Di Bella template <std::input_or_output_iterator T>
5239034388SChristopher Di Bella   requires(!std::input_iterator<T>)
requires_input_iterator()5339034388SChristopher Di Bella void requires_input_iterator() {
5439034388SChristopher Di Bella   struct bad_range {
5539034388SChristopher Di Bella     T begin();
5639034388SChristopher Di Bella     std::unreachable_sentinel_t end();
5739034388SChristopher Di Bella   };
5839034388SChristopher Di Bella 
5939034388SChristopher Di Bella   static_assert(!requires(bad_range r) {
6039034388SChristopher Di Bella     std::ranges::fold_left_with_iter(r.begin(), r.end(), std::unreachable_sentinel, 0, std::plus());
6139034388SChristopher Di Bella   });
6239034388SChristopher Di Bella   static_assert(!requires(bad_range r) { std::ranges::fold_left_with_iter(r, 0, std::plus()); });
6339034388SChristopher Di Bella 
6439034388SChristopher Di Bella   static_assert(!requires(bad_range r) {
6539034388SChristopher Di Bella     std::ranges::fold_left(r.begin(), r.end(), std::unreachable_sentinel, 0, std::plus());
6639034388SChristopher Di Bella   });
6739034388SChristopher Di Bella 
6839034388SChristopher Di Bella   static_assert(!requires(bad_range r) { std::ranges::fold_left(r, 0, std::plus()); });
6939034388SChristopher Di Bella }
7039034388SChristopher Di Bella 
7139034388SChristopher Di Bella template <std::equality_comparable S>
7239034388SChristopher Di Bella   requires(!std::sentinel_for<int*, S>)
requires_sentinel()7339034388SChristopher Di Bella void requires_sentinel() {
7439034388SChristopher Di Bella   static_assert(!requires(S first, S last) { std::ranges::fold_left_with_iter(first, last, 0, std::plus()); });
7539034388SChristopher Di Bella   static_assert(!requires(S first, S last) { std::ranges::fold_left(first, last, 0, std::plus()); });
7639034388SChristopher Di Bella }
7739034388SChristopher Di Bella 
7839034388SChristopher Di Bella struct non_copy_constructible_callable {
7939034388SChristopher Di Bella   non_copy_constructible_callable(non_copy_constructible_callable&&)      = default;
8039034388SChristopher Di Bella   non_copy_constructible_callable(non_copy_constructible_callable const&) = delete;
8139034388SChristopher Di Bella 
8239034388SChristopher Di Bella   int operator()(int, int) const;
8339034388SChristopher Di Bella };
8439034388SChristopher Di Bella 
8539034388SChristopher Di Bella template <class F>
8639034388SChristopher Di Bella   requires(!std::copy_constructible<F>)
requires_copy_constructible_F()8739034388SChristopher Di Bella void requires_copy_constructible_F() {
8839034388SChristopher Di Bella   static_assert(!requires(std::ranges::subrange<int*, int*> r, F f) {
8939034388SChristopher Di Bella     std::ranges::fold_left_with_iter(r.begin(), r.end(), 0, std::move(f));
9039034388SChristopher Di Bella   });
9139034388SChristopher Di Bella   static_assert(!requires(std::ranges::subrange<int*, int*> r, F f) {
9239034388SChristopher Di Bella     std::ranges::fold_left_with_iter(r, 0, std::move(f));
9339034388SChristopher Di Bella   });
9439034388SChristopher Di Bella 
9539034388SChristopher Di Bella   static_assert(!requires(std::ranges::subrange<int*, int*> r, F f) {
9639034388SChristopher Di Bella     std::ranges::fold_left(r.begin(), r.end(), 0, std::move(f));
9739034388SChristopher Di Bella   });
9839034388SChristopher Di Bella   static_assert(!requires(std::ranges::subrange<int*, int*> r, F f) { std::ranges::fold_left(r, 0, std::move(f)); });
9939034388SChristopher Di Bella }
10039034388SChristopher Di Bella 
10139034388SChristopher Di Bella struct not_invocable_with_lvalue_rhs {
10239034388SChristopher Di Bella   int operator()(int, int&&);
10339034388SChristopher Di Bella };
10439034388SChristopher Di Bella 
10539034388SChristopher Di Bella template <class F>
10639034388SChristopher Di Bella   requires(!std::invocable<F&, int, std::iter_reference_t<int*>>)
requires_raw_invocable()10739034388SChristopher Di Bella void requires_raw_invocable() {
10839034388SChristopher Di Bella   static_assert(!requires(std::ranges::subrange<int*, int*> r, F f) {
10939034388SChristopher Di Bella     std::ranges::fold_left_with_iter(r.begin(), r.end(), 0, f);
11039034388SChristopher Di Bella   });
11139034388SChristopher Di Bella   static_assert(!requires(std::ranges::subrange<int*, int*> r, F f) { std::ranges::fold_left_with_iter(r, 0, f); });
11239034388SChristopher Di Bella 
11339034388SChristopher Di Bella   static_assert(!requires(std::ranges::subrange<int*, int*> r, F f) {
11439034388SChristopher Di Bella     std::ranges::fold_left(r.begin(), r.end(), 0, f);
11539034388SChristopher Di Bella   });
11639034388SChristopher Di Bella   static_assert(!requires(std::ranges::subrange<int*, int*> r, F f) { std::ranges::fold_left(r, 0, f); });
11739034388SChristopher Di Bella }
11839034388SChristopher Di Bella 
11939034388SChristopher Di Bella struct S {};
12039034388SChristopher Di Bella 
12139034388SChristopher Di Bella struct non_decayable_result {
12239034388SChristopher Di Bella   S volatile& operator()(S, S) const;
12339034388SChristopher Di Bella };
12439034388SChristopher Di Bella 
12539034388SChristopher Di Bella template <std::invocable<S, std::iter_reference_t<S*>> F>
12639034388SChristopher Di Bella   requires(!std::convertible_to<std::invoke_result_t<F&, S, std::iter_reference_t<S*>>,
12739034388SChristopher Di Bella                                 std::decay_t<std::invoke_result_t<F&, S, std::iter_reference_t<S*>>>>)
requires_decaying_invoke_result()12839034388SChristopher Di Bella void requires_decaying_invoke_result() {
12939034388SChristopher Di Bella   static_assert(!requires(std::ranges::subrange<S*, S*> r, S init, F f) {
13039034388SChristopher Di Bella     std::ranges::fold_left_with_iter(r.begin(), r.end(), init, f);
13139034388SChristopher Di Bella   });
13239034388SChristopher Di Bella   static_assert(!requires(std::ranges::subrange<S*, S*> r, S init, F f) {
13339034388SChristopher Di Bella     std::ranges::fold_left_with_iter(r, init, f);
13439034388SChristopher Di Bella   });
13539034388SChristopher Di Bella 
13639034388SChristopher Di Bella   static_assert(!requires(std::ranges::subrange<S*, S*> r, S init, F f) {
13739034388SChristopher Di Bella     std::ranges::fold_left(r.begin(), r.end(), init, f);
13839034388SChristopher Di Bella   });
13939034388SChristopher Di Bella   static_assert(!requires(std::ranges::subrange<S*, S*> r, S init, F f) { std::ranges::fold_left(r, init, f); });
14039034388SChristopher Di Bella }
14139034388SChristopher Di Bella 
14239034388SChristopher Di Bella struct non_movable {
14339034388SChristopher Di Bella   non_movable(int);
14439034388SChristopher Di Bella   non_movable(non_movable&&) = delete;
14539034388SChristopher Di Bella 
14639034388SChristopher Di Bella   int apply(non_movable const&) const;
14739034388SChristopher Di Bella };
14839034388SChristopher Di Bella 
14939034388SChristopher Di Bella template <class T>
15039034388SChristopher Di Bella   requires(!std::movable<T>)
requires_movable_init()15139034388SChristopher Di Bella void requires_movable_init() {
15239034388SChristopher Di Bella   static_assert(!requires(std::ranges::subrange<T*, T*> r, T init) {
15339034388SChristopher Di Bella     std::ranges::fold_left_with_iter(r.begin(), r.end(), init, &T::apply);
15439034388SChristopher Di Bella   });
15539034388SChristopher Di Bella   static_assert(!requires(std::ranges::subrange<T*, T*> r, T init) {
15639034388SChristopher Di Bella     std::ranges::fold_left_with_iter(r, init, &T::apply);
15739034388SChristopher Di Bella   });
15839034388SChristopher Di Bella   static_assert(!requires(std::ranges::subrange<T*, T*> r, T init) {
15939034388SChristopher Di Bella     std::ranges::fold_left(r.begin(), r.end(), init, &T::apply);
16039034388SChristopher Di Bella   });
16139034388SChristopher Di Bella   static_assert(!requires(std::ranges::subrange<T*, T*> r, T init) { std::ranges::fold_left(r, init, &T::apply); });
16239034388SChristopher Di Bella }
16339034388SChristopher Di Bella 
16439034388SChristopher Di Bella struct result_not_movable_after_decay {
16539034388SChristopher Di Bella   result_not_movable_after_decay(int);
16639034388SChristopher Di Bella   result_not_movable_after_decay(result_not_movable_after_decay&&) = delete;
16739034388SChristopher Di Bella   result_not_movable_after_decay(result_not_movable_after_decay const&);
16839034388SChristopher Di Bella 
16939034388SChristopher Di Bella   friend result_not_movable_after_decay const& operator+(int, result_not_movable_after_decay const&);
17039034388SChristopher Di Bella   friend result_not_movable_after_decay const& operator+(result_not_movable_after_decay const&, int);
17139034388SChristopher Di Bella   friend result_not_movable_after_decay const&
17239034388SChristopher Di Bella   operator+(result_not_movable_after_decay const&, result_not_movable_after_decay const&);
17339034388SChristopher Di Bella };
17439034388SChristopher Di Bella 
17539034388SChristopher Di Bella template <class T>
17639034388SChristopher Di Bella   requires(!std::movable<T>)
requires_movable_decayed()17739034388SChristopher Di Bella void requires_movable_decayed() {
17839034388SChristopher Di Bella   static_assert(!requires(std::ranges::subrange<T*, T*> r) {
17939034388SChristopher Di Bella     std::ranges::fold_left_with_iter(r.begin(), r.end(), 0, std::plus());
18039034388SChristopher Di Bella   });
18139034388SChristopher Di Bella   static_assert(!requires(std::ranges::subrange<T*, T*> r) { std::ranges::fold_left_with_iter(r, 0, std::plus()); });
18239034388SChristopher Di Bella 
18339034388SChristopher Di Bella   static_assert(!requires(std::ranges::subrange<T*, T*> r) {
18439034388SChristopher Di Bella     std::ranges::fold_left(r.begin(), r.end(), 0, T::apply);
18539034388SChristopher Di Bella   });
18639034388SChristopher Di Bella   static_assert(!requires(std::ranges::subrange<T*, T*> r) { std::ranges::fold_left(r, 0, std::plus()); });
18739034388SChristopher Di Bella }
18839034388SChristopher Di Bella 
18939034388SChristopher Di Bella struct not_convertible_to_int {
19039034388SChristopher Di Bella   friend int operator+(not_convertible_to_int, not_convertible_to_int);
19139034388SChristopher Di Bella   friend int operator+(not_convertible_to_int, int);
19239034388SChristopher Di Bella   friend int operator+(int, not_convertible_to_int);
19339034388SChristopher Di Bella };
19439034388SChristopher Di Bella 
19539034388SChristopher Di Bella template <class T>
19639034388SChristopher Di Bella   requires(!std::convertible_to<T, int>)
requires_init_is_convertible_to_decayed()19739034388SChristopher Di Bella void requires_init_is_convertible_to_decayed() {
19839034388SChristopher Di Bella   static_assert(!requires(std::ranges::subrange<int*, int*> r, T init) {
19939034388SChristopher Di Bella     std::ranges::fold_left_with_iter(r.begin(), r.end(), init, std::plus());
20039034388SChristopher Di Bella   });
20139034388SChristopher Di Bella   static_assert(!requires(std::ranges::subrange<int*, int*> r, T init) {
20239034388SChristopher Di Bella     std::ranges::fold_left_with_iter(r, init, std::plus());
20339034388SChristopher Di Bella   });
20439034388SChristopher Di Bella 
20539034388SChristopher Di Bella   static_assert(!requires(std::ranges::subrange<int*, int*> r, T init) {
20639034388SChristopher Di Bella     std::ranges::fold_left(r.begin(), r.end(), init, std::plus());
20739034388SChristopher Di Bella   });
20839034388SChristopher Di Bella   static_assert(!requires(std::ranges::subrange<int*, int*> r, T init) {
20939034388SChristopher Di Bella     std::ranges::fold_left(r, init, std::plus());
21039034388SChristopher Di Bella   });
21139034388SChristopher Di Bella }
21239034388SChristopher Di Bella 
21339034388SChristopher Di Bella struct not_invocable_with_decayed {
21439034388SChristopher Di Bella   not_invocable_with_decayed(int);
21539034388SChristopher Di Bella   friend not_invocable_with_decayed& operator+(int, not_invocable_with_decayed&);
21639034388SChristopher Di Bella   friend not_invocable_with_decayed& operator+(not_invocable_with_decayed&, int);
21739034388SChristopher Di Bella   friend not_invocable_with_decayed& operator+(not_invocable_with_decayed volatile&, not_invocable_with_decayed&);
21839034388SChristopher Di Bella };
21939034388SChristopher Di Bella 
22039034388SChristopher Di Bella template <class T>
22139034388SChristopher Di Bella   requires(!std::invocable<std::plus<>&, T, T&>)
requires_invocable_with_decayed()22239034388SChristopher Di Bella void requires_invocable_with_decayed() {
22339034388SChristopher Di Bella   static_assert(!requires(std::ranges::subrange<T*, T*> r, int init) {
22439034388SChristopher Di Bella     std::ranges::fold_left_with_iter(r.begin(), r.end(), init, std::plus());
22539034388SChristopher Di Bella   });
22639034388SChristopher Di Bella   static_assert(!requires(std::ranges::subrange<T*, T*> r, int init) {
22739034388SChristopher Di Bella     std::ranges::fold_left_with_iter(r, init, std::plus());
22839034388SChristopher Di Bella   });
22939034388SChristopher Di Bella 
23039034388SChristopher Di Bella   static_assert(!requires(std::ranges::subrange<T*, T*> r, int init) {
23139034388SChristopher Di Bella     std::ranges::fold_left(r.begin(), r.end(), init, std::plus());
23239034388SChristopher Di Bella   });
23339034388SChristopher Di Bella   static_assert(!requires(std::ranges::subrange<T*, T*> r, int init) { std::ranges::fold_left(r, init, std::plus()); });
23439034388SChristopher Di Bella }
23539034388SChristopher Di Bella 
23639034388SChristopher Di Bella struct not_assignable_to_decayed {
23739034388SChristopher Di Bella   not_assignable_to_decayed();
23839034388SChristopher Di Bella   not_assignable_to_decayed(not_assignable_to_decayed&);
23939034388SChristopher Di Bella   not_assignable_to_decayed(not_assignable_to_decayed const&);
24039034388SChristopher Di Bella   not_assignable_to_decayed(not_assignable_to_decayed volatile&);
24139034388SChristopher Di Bella   not_assignable_to_decayed(not_assignable_to_decayed const volatile&);
24239034388SChristopher Di Bella   friend not_assignable_to_decayed volatile& operator+(not_assignable_to_decayed, not_assignable_to_decayed);
24339034388SChristopher Di Bella };
24439034388SChristopher Di Bella 
24539034388SChristopher Di Bella template <class T>
24639034388SChristopher Di Bella   requires(!std::assignable_from<T&, T volatile&>)
requires_assignable_from_invoke_result()24739034388SChristopher Di Bella void requires_assignable_from_invoke_result() {
24839034388SChristopher Di Bella   static_assert(!requires(std::ranges::subrange<T*, T*> r, T init) {
24939034388SChristopher Di Bella     std::ranges::fold_left_with_iter(r.begin(), r.end(), init, std::plus());
25039034388SChristopher Di Bella   });
25139034388SChristopher Di Bella   static_assert(!requires(std::ranges::subrange<T*, T*> r, T init) {
25239034388SChristopher Di Bella     std::ranges::fold_left_with_iter(r, init, std::plus());
25339034388SChristopher Di Bella   });
25439034388SChristopher Di Bella 
25539034388SChristopher Di Bella   static_assert(!requires(std::ranges::subrange<T*, T*> r, T init) {
25639034388SChristopher Di Bella     std::ranges::fold_left(r.begin(), r.end(), init, std::plus());
25739034388SChristopher Di Bella   });
25839034388SChristopher Di Bella   static_assert(!requires(std::ranges::subrange<T*, T*> r, T init) { std::ranges::fold_left(r, init, std::plus()); });
25939034388SChristopher Di Bella }
26039034388SChristopher Di Bella 
test()26139034388SChristopher Di Bella void test() {
26239034388SChristopher Di Bella   requires_input_iterator<bad_iterator_category>();
26339034388SChristopher Di Bella   requires_sentinel<cpp17_input_iterator<int*>>();
26439034388SChristopher Di Bella   requires_copy_constructible_F<non_copy_constructible_callable>();
26539034388SChristopher Di Bella   requires_raw_invocable<not_invocable_with_lvalue_rhs>();
26639034388SChristopher Di Bella   requires_decaying_invoke_result<non_decayable_result>();
26739034388SChristopher Di Bella   requires_movable_init<non_movable>();
26839034388SChristopher Di Bella   requires_movable_decayed<result_not_movable_after_decay>();
26939034388SChristopher Di Bella   requires_init_is_convertible_to_decayed<not_convertible_to_int>();
27039034388SChristopher Di Bella   requires_invocable_with_decayed<not_invocable_with_decayed>();
27139034388SChristopher Di Bella   requires_assignable_from_invoke_result<not_assignable_to_decayed>();
27239034388SChristopher Di Bella }
273