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 I>
12// concept indirectly_regular_unary_invocable;
13
14#include <iterator>
15#include <concepts>
16
17#include "indirectly_readable.h"
18#include "test_macros.h"
19
20using It = IndirectlyReadable<struct Token>;
21using R1 = T1<struct ReturnToken>;
22using R2 = T2<struct ReturnToken>;
23
24template <class I>
25struct GoodInvocable {
26 R1 operator()(std::iter_value_t<I>&) const;
27 R2 operator()(std::iter_reference_t<I>) const;
28 R2 operator()(std::iter_common_reference_t<I>) const;
29};
30
31// Should work when all constraints are satisfied
32static_assert(std::indirectly_regular_unary_invocable<GoodInvocable<It>, It>);
33
34// Should fail when the iterator is not indirectly_readable
35struct NotIndirectlyReadable { };
36static_assert(!std::indirectly_regular_unary_invocable<GoodInvocable<NotIndirectlyReadable>, NotIndirectlyReadable>);
37
38// Should fail when the invocable is not copy constructible
39struct BadInvocable1 {
40 BadInvocable1(BadInvocable1 const&) = delete;
41 template <class T> R1 operator()(T const&) const;
42};
43static_assert(!std::indirectly_regular_unary_invocable<BadInvocable1, It>);
44
45// Should fail when the invocable can't be called with (iter_value_t&)
46struct BadInvocable2 {
47 template <class T> R1 operator()(T const&) const;
48 R1 operator()(std::iter_value_t<It>&) const = delete;
49};
50static_assert(!std::indirectly_regular_unary_invocable<BadInvocable2, It>);
51
52// Should fail when the invocable can't be called with (iter_reference_t)
53struct BadInvocable3 {
54 template <class T> R1 operator()(T const&) const;
55 R1 operator()(std::iter_reference_t<It>) const = delete;
56};
57static_assert(!std::indirectly_regular_unary_invocable<BadInvocable3, It>);
58
59// This case was made valid by P2997R1.
60struct GoodInvocable4 {
61 template <class T>
62 R1 operator()(T const&) const;
63 R1 operator()(std::iter_common_reference_t<It>) const = delete;
64};
65static_assert(std::indirectly_regular_unary_invocable<GoodInvocable4, It>);
66
67// Should fail when the invocable doesn't have a common reference between its return types
68struct BadInvocable5 {
69 R1 operator()(std::iter_value_t<It>&) const;
70 struct Unrelated { };
71 Unrelated operator()(std::iter_reference_t<It>) const;
72 R1 operator()(std::iter_common_reference_t<It>) const;
73};
74static_assert(!std::indirectly_regular_unary_invocable<BadInvocable5, It>);
75
76// Various tests with callables
77struct S;
78static_assert(std::indirectly_regular_unary_invocable<int (*)(int), int*>);
79static_assert(std::indirectly_regular_unary_invocable<int (&)(int), int*>);
80static_assert(std::indirectly_regular_unary_invocable<int S::*, S*>);
81static_assert(std::indirectly_regular_unary_invocable<int (S::*)(), S*>);
82static_assert(std::indirectly_regular_unary_invocable<int (S::*)() const, S*>);
83static_assert(std::indirectly_regular_unary_invocable<void(*)(int), int*>);
84
85static_assert(!std::indirectly_regular_unary_invocable<int(int), int*>); // not move constructible
86static_assert(!std::indirectly_regular_unary_invocable<int (*)(int*, int*), int*>);
87static_assert(!std::indirectly_regular_unary_invocable<int (&)(int*, int*), int*>);
88static_assert(!std::indirectly_regular_unary_invocable<int (S::*)(int*), S*>);
89static_assert(!std::indirectly_regular_unary_invocable<int (S::*)(int*) const, S*>);
90
91// Test ADL-proofing (P2538R1)
92#if TEST_STD_VER >= 26 || defined(_LIBCPP_VERSION)
93struct Incomplete;
94template<class T> struct Holder { T t; };
95struct HolderIncompletePred { bool operator()(Holder<Incomplete>*) const; };
96static_assert(std::indirectly_regular_unary_invocable<HolderIncompletePred, Holder<Incomplete>**>);
97static_assert(!std::indirectly_regular_unary_invocable<Holder<Incomplete>*, Holder<Incomplete>**>);
98#endif
99

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