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 
28 struct Tag {};
29 struct DerFromTag : Tag {};
30 
31 struct Implicit {
ImplicitImplicit32   Implicit(int) {}
33 };
34 
35 struct Explicit {
ExplicitExplicit36   explicit Explicit(int) {}
37 };
38 
39 struct NotCallableWithInt {
40   int operator()(int) = delete;
operator ()NotCallableWithInt41   int operator()(Tag) { return 42; }
42 };
43 
44 struct Sink {
45   template <class ...Args>
operator ()Sink46   void operator()(Args&&...) const {}
47 };
48 
main(int,char **)49 int 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