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
10
11// type_traits
12
13// is_invocable
14
15// Most testing of is_invocable is done within the [meta.trans.other] result_of
16// tests.
17
18// Fn and all types in the template parameter pack ArgTypes shall be
19// complete types, cv void, or arrays of unknown bound.
20
21#include <cstddef>
22#include <functional>
23#include <memory>
24#include <type_traits>
25#include <vector>
26
27struct Tag {};
28struct DerFromTag : Tag {};
29
30struct Implicit {
31 Implicit(int) {}
32};
33
34struct Explicit {
35 explicit Explicit(int) {}
36};
37
38struct NotCallableWithInt {
39 int operator()(int) = delete;
40 int operator()(Tag) { return 42; }
41};
42
43struct Sink {
44 template <class ...Args>
45 void operator()(Args&&...) const {}
46};
47
48int main(int, char**) {
49 using AbominableFunc = void(...) const;
50
51 // Non-callable things
52 {
53 static_assert(!std::is_invocable<void>::value, "");
54 static_assert(!std::is_invocable<const void>::value, "");
55 static_assert(!std::is_invocable<volatile void>::value, "");
56 static_assert(!std::is_invocable<const volatile void>::value, "");
57 static_assert(!std::is_invocable<std::nullptr_t>::value, "");
58 static_assert(!std::is_invocable<int>::value, "");
59 static_assert(!std::is_invocable<double>::value, "");
60
61 static_assert(!std::is_invocable<int[]>::value, "");
62 static_assert(!std::is_invocable<int[3]>::value, "");
63
64 static_assert(!std::is_invocable<int*>::value, "");
65 static_assert(!std::is_invocable<const int*>::value, "");
66 static_assert(!std::is_invocable<int const*>::value, "");
67
68 static_assert(!std::is_invocable<int&>::value, "");
69 static_assert(!std::is_invocable<const int&>::value, "");
70 static_assert(!std::is_invocable<int&&>::value, "");
71
72 static_assert(!std::is_invocable<std::vector<int> >::value, "");
73 static_assert(!std::is_invocable<std::vector<int*> >::value, "");
74 static_assert(!std::is_invocable<std::vector<int**> >::value, "");
75
76 static_assert(!std::is_invocable<AbominableFunc>::value, "");
77
78 // with parameters
79 static_assert(!std::is_invocable<int, int>::value, "");
80 static_assert(!std::is_invocable<int, double, float>::value, "");
81 static_assert(!std::is_invocable<int, char, float, double>::value, "");
82 static_assert(!std::is_invocable<Sink, AbominableFunc>::value, "");
83 static_assert(!std::is_invocable<Sink, void>::value, "");
84 static_assert(!std::is_invocable<Sink, const volatile void>::value,
85 "");
86
87
88 static_assert(!std::is_invocable_r<int, void>::value, "");
89 static_assert(!std::is_invocable_r<int, const void>::value, "");
90 static_assert(!std::is_invocable_r<int, volatile void>::value, "");
91 static_assert(!std::is_invocable_r<int, const volatile void>::value, "");
92 static_assert(!std::is_invocable_r<int, std::nullptr_t>::value, "");
93 static_assert(!std::is_invocable_r<int, int>::value, "");
94 static_assert(!std::is_invocable_r<int, double>::value, "");
95
96 static_assert(!std::is_invocable_r<int, int[]>::value, "");
97 static_assert(!std::is_invocable_r<int, int[3]>::value, "");
98
99 static_assert(!std::is_invocable_r<int, int*>::value, "");
100 static_assert(!std::is_invocable_r<int, const int*>::value, "");
101 static_assert(!std::is_invocable_r<int, int const*>::value, "");
102
103 static_assert(!std::is_invocable_r<int, int&>::value, "");
104 static_assert(!std::is_invocable_r<int, const int&>::value, "");
105 static_assert(!std::is_invocable_r<int, int&&>::value, "");
106
107 static_assert(!std::is_invocable_r<int, std::vector<int> >::value, "");
108 static_assert(!std::is_invocable_r<int, std::vector<int*> >::value, "");
109 static_assert(!std::is_invocable_r<int, std::vector<int**> >::value, "");
110 static_assert(!std::is_invocable_r<void, AbominableFunc>::value, "");
111
112 // with parameters
113 static_assert(!std::is_invocable_r<int, int, int>::value, "");
114 static_assert(!std::is_invocable_r<int, int, double, float>::value, "");
115 static_assert(!std::is_invocable_r<int, int, char, float, double>::value,
116 "");
117 static_assert(!std::is_invocable_r<void, Sink, AbominableFunc>::value, "");
118 static_assert(!std::is_invocable_r<void, Sink, void>::value, "");
119 static_assert(!std::is_invocable_r<void, Sink, const volatile void>::value,
120 "");
121 }
122 {
123 using Fn = int (Tag::*)(int);
124 using RFn = int (Tag::*)(int)&&;
125 // INVOKE bullet 1, 2 and 3
126 {
127 // Bullet 1
128 static_assert(std::is_invocable<Fn, Tag&, int>::value, "");
129 static_assert(std::is_invocable<Fn, DerFromTag&, int>::value, "");
130 static_assert(std::is_invocable<RFn, Tag&&, int>::value, "");
131 static_assert(!std::is_invocable<RFn, Tag&, int>::value, "");
132 static_assert(!std::is_invocable<Fn, Tag&>::value, "");
133 static_assert(!std::is_invocable<Fn, Tag const&, int>::value, "");
134 }
135 {
136 // Bullet 2
137 using T = std::reference_wrapper<Tag>;
138 using DT = std::reference_wrapper<DerFromTag>;
139 using CT = std::reference_wrapper<const Tag>;
140 static_assert(std::is_invocable<Fn, T&, int>::value, "");
141 static_assert(std::is_invocable<Fn, DT&, int>::value, "");
142 static_assert(std::is_invocable<Fn, const T&, int>::value, "");
143 static_assert(std::is_invocable<Fn, T&&, int>::value, "");
144 static_assert(!std::is_invocable<Fn, CT&, int>::value, "");
145 static_assert(!std::is_invocable<RFn, T, int>::value, "");
146 }
147 {
148 // Bullet 3
149 using T = Tag*;
150 using DT = DerFromTag*;
151 using CT = const Tag*;
152 using ST = std::unique_ptr<Tag>;
153 static_assert(std::is_invocable<Fn, T&, int>::value, "");
154 static_assert(std::is_invocable<Fn, DT&, int>::value, "");
155 static_assert(std::is_invocable<Fn, const T&, int>::value, "");
156 static_assert(std::is_invocable<Fn, T&&, int>::value, "");
157 static_assert(std::is_invocable<Fn, ST, int>::value, "");
158 static_assert(!std::is_invocable<Fn, CT&, int>::value, "");
159 static_assert(!std::is_invocable<RFn, T, int>::value, "");
160 }
161 }
162 {
163 // Bullets 4, 5 and 6
164 using Fn = int(Tag::*);
165 static_assert(!std::is_invocable<Fn>::value, "");
166 {
167 // Bullet 4
168 static_assert(std::is_invocable<Fn, Tag&>::value, "");
169 static_assert(std::is_invocable<Fn, DerFromTag&>::value, "");
170 static_assert(std::is_invocable<Fn, Tag&&>::value, "");
171 static_assert(std::is_invocable<Fn, Tag const&>::value, "");
172 }
173 {
174 // Bullet 5
175 using T = std::reference_wrapper<Tag>;
176 using DT = std::reference_wrapper<DerFromTag>;
177 using CT = std::reference_wrapper<const Tag>;
178 static_assert(std::is_invocable<Fn, T&>::value, "");
179 static_assert(std::is_invocable<Fn, DT&>::value, "");
180 static_assert(std::is_invocable<Fn, const T&>::value, "");
181 static_assert(std::is_invocable<Fn, T&&>::value, "");
182 static_assert(std::is_invocable<Fn, CT&>::value, "");
183 }
184 {
185 // Bullet 6
186 using T = Tag*;
187 using DT = DerFromTag*;
188 using CT = const Tag*;
189 using ST = std::unique_ptr<Tag>;
190 static_assert(std::is_invocable<Fn, T&>::value, "");
191 static_assert(std::is_invocable<Fn, DT&>::value, "");
192 static_assert(std::is_invocable<Fn, const T&>::value, "");
193 static_assert(std::is_invocable<Fn, T&&>::value, "");
194 static_assert(std::is_invocable<Fn, ST>::value, "");
195 static_assert(std::is_invocable<Fn, CT&>::value, "");
196 }
197 }
198 { // INVOKE bullet 7
199 {// Function pointer
200 using Fp = void(*)(Tag&, int);
201 static_assert(std::is_invocable<Fp, Tag&, int>::value, "");
202 static_assert(std::is_invocable<Fp, DerFromTag&, int>::value, "");
203 static_assert(!std::is_invocable<Fp, const Tag&, int>::value, "");
204 static_assert(!std::is_invocable<Fp>::value, "");
205 static_assert(!std::is_invocable<Fp, Tag&>::value, "");
206}
207{
208 // Function reference
209 using Fp = void (&)(Tag&, int);
210 static_assert(std::is_invocable<Fp, Tag&, int>::value, "");
211 static_assert(std::is_invocable<Fp, DerFromTag&, int>::value, "");
212 static_assert(!std::is_invocable<Fp, const Tag&, int>::value, "");
213 static_assert(!std::is_invocable<Fp>::value, "");
214 static_assert(!std::is_invocable<Fp, Tag&>::value, "");
215}
216{
217 // Function object
218 using Fn = NotCallableWithInt;
219 static_assert(std::is_invocable<Fn, Tag>::value, "");
220 static_assert(!std::is_invocable<Fn, int>::value, "");
221}
222}
223{
224 // Check that the conversion to the return type is properly checked
225 using Fn = int (*)();
226 static_assert(std::is_invocable_r<Implicit, Fn>::value, "");
227 static_assert(std::is_invocable_r<double, Fn>::value, "");
228 static_assert(std::is_invocable_r<const volatile void, Fn>::value, "");
229 static_assert(!std::is_invocable_r<Explicit, Fn>::value, "");
230}
231{
232 // Check for is_invocable_v
233 using Fn = void (*)();
234 static_assert(std::is_invocable_v<Fn>, "");
235 static_assert(!std::is_invocable_v<Fn, int>, "");
236}
237{
238 // Check for is_invocable_r_v
239 using Fn = void (*)();
240 static_assert(std::is_invocable_r_v<void, Fn>, "");
241 static_assert(!std::is_invocable_r_v<int, Fn>, "");
242}
243 return 0;
244}
245

source code of libcxx/test/std/utilities/meta/meta.rel/is_invocable.pass.cpp