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

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