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