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
21using It1 = IndirectlyReadable<struct Token1>;
22using It2 = IndirectlyReadable<struct Token2>;
23
24template <class I1, class I2>
25struct 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
34static_assert(std::indirect_binary_predicate<GoodPredicate<It1, It2>, It1, It2>);
35static_assert(std::indirect_binary_predicate<bool(*)(int, float), int*, float*>);
36[[maybe_unused]] auto lambda = [](int i, int j) { return i < j; };
37static_assert(std::indirect_binary_predicate<decltype(lambda), int*, int*>);
38
39// Should fail when either of the iterators is not indirectly_readable
40struct NotIndirectlyReadable { };
41static_assert(!std::indirect_binary_predicate<GoodPredicate<It1, NotIndirectlyReadable>, It1, NotIndirectlyReadable>);
42static_assert(!std::indirect_binary_predicate<GoodPredicate<NotIndirectlyReadable, It2>, NotIndirectlyReadable, It2>);
43
44// Should fail when the predicate is not copy constructible
45struct BadPredicate1 {
46 BadPredicate1(BadPredicate1 const&) = delete;
47 template <class T, class U> bool operator()(T const&, U const&) const;
48};
49static_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&)
52struct 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};
56static_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)
59struct 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};
63static_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&)
66struct 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};
70static_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)
73struct 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};
77static_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)
80struct 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};
84static_assert(!std::indirect_binary_predicate<BadPredicate6, It1, It2>);
85
86// Test ADL-proofing (P2538R1)
87#if TEST_STD_VER >= 26 || defined(_LIBCPP_VERSION)
88struct Incomplete;
89template<class T> struct Holder { T t; };
90static_assert(std::indirect_binary_predicate<std::less<Holder<Incomplete>*>, Holder<Incomplete>**, Holder<Incomplete>**>);
91static_assert(!std::indirect_binary_predicate<Holder<Incomplete>*, Holder<Incomplete>**, Holder<Incomplete>**>);
92#endif
93

source code of libcxx/test/std/iterators/iterator.requirements/indirectcallable/indirectinvocable/indirect_binary_predicate.compile.pass.cpp