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-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 // UNSUPPORTED: c++03, c++11, c++14, c++17
10 
11 // template<class F, class I1, class I2>
12 // concept indirect_binary_predicate;
13 
14 #include <iterator>
15 #include <type_traits>
16 
17 #include "indirectly_readable.h"
18 
19 using It1 = IndirectlyReadable<struct Token1>;
20 using It2 = IndirectlyReadable<struct Token2>;
21 
22 template <class I1, class I2>
23 struct GoodPredicate {
24     bool operator()(std::iter_value_t<I1>&, std::iter_value_t<I2>&) const;
25     bool operator()(std::iter_value_t<I1>&, std::iter_reference_t<I2>) const;
26     bool operator()(std::iter_reference_t<I1>, std::iter_value_t<I2>&) const;
27     bool operator()(std::iter_reference_t<I1>, std::iter_reference_t<I2>) const;
28     bool operator()(std::iter_common_reference_t<I1>, std::iter_common_reference_t<I2>) const;
29 };
30 
31 // Should work when all constraints are satisfied
32 static_assert(std::indirect_binary_predicate<GoodPredicate<It1, It2>, It1, It2>);
33 static_assert(std::indirect_binary_predicate<bool(*)(int, float), int*, float*>);
__anond3de8c900102(int i, int j) 34 [[maybe_unused]] auto lambda = [](int i, int j) { return i < j; };
35 static_assert(std::indirect_binary_predicate<decltype(lambda), int*, int*>);
36 
37 // Should fail when either of the iterators is not indirectly_readable
38 struct NotIndirectlyReadable { };
39 static_assert(!std::indirect_binary_predicate<GoodPredicate<It1, NotIndirectlyReadable>, It1, NotIndirectlyReadable>);
40 static_assert(!std::indirect_binary_predicate<GoodPredicate<NotIndirectlyReadable, It2>, NotIndirectlyReadable, It2>);
41 
42 // Should fail when the predicate is not copy constructible
43 struct BadPredicate1 {
44     BadPredicate1(BadPredicate1 const&) = delete;
45     template <class T, class U> bool operator()(T const&, U const&) const;
46 };
47 static_assert(!std::indirect_binary_predicate<BadPredicate1, It1, It2>);
48 
49 // Should fail when the predicate can't be called with (iter_value_t&, iter_value_t&)
50 struct BadPredicate2 {
51     template <class T, class U> bool operator()(T const&, U const&) const;
52     bool operator()(std::iter_value_t<It1>&, std::iter_value_t<It2>&) const = delete;
53 };
54 static_assert(!std::indirect_binary_predicate<BadPredicate2, It1, It2>);
55 
56 // Should fail when the predicate can't be called with (iter_value_t&, iter_reference_t)
57 struct BadPredicate3 {
58     template <class T, class U> bool operator()(T const&, U const&) const;
59     bool operator()(std::iter_value_t<It1>&, std::iter_reference_t<It2>) const = delete;
60 };
61 static_assert(!std::indirect_binary_predicate<BadPredicate3, It1, It2>);
62 
63 // Should fail when the predicate can't be called with (iter_reference_t, iter_value_t&)
64 struct BadPredicate4 {
65     template <class T, class U> bool operator()(T const&, U const&) const;
66     bool operator()(std::iter_reference_t<It1>, std::iter_value_t<It2>&) const = delete;
67 };
68 static_assert(!std::indirect_binary_predicate<BadPredicate4, It1, It2>);
69 
70 // Should fail when the predicate can't be called with (iter_reference_t, iter_reference_t)
71 struct BadPredicate5 {
72     template <class T, class U> bool operator()(T const&, U const&) const;
73     bool operator()(std::iter_reference_t<It1>, std::iter_reference_t<It2>) const = delete;
74 };
75 static_assert(!std::indirect_binary_predicate<BadPredicate5, It1, It2>);
76 
77 // Should fail when the predicate can't be called with (iter_common_reference_t, iter_common_reference_t)
78 struct BadPredicate6 {
79     template <class T, class U> bool operator()(T const&, U const&) const;
80     bool operator()(std::iter_common_reference_t<It1>, std::iter_common_reference_t<It2>) const = delete;
81 };
82 static_assert(!std::indirect_binary_predicate<BadPredicate6, It1, It2>);
83