xref: /aosp_15_r20/external/libcxx/test/std/utilities/meta/meta.rel/is_invocable.pass.cpp (revision 58b9f456b02922dfdb1fad8a988d5fd8765ecb80)
1 //===----------------------------------------------------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is dual licensed under the MIT and the University of Illinois Open
6 // Source Licenses. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 // UNSUPPORTED: c++98, c++03, c++11, c++14
11 
12 // type_traits
13 
14 // is_invocable
15 
16 // Most testing of is_invocable is done within the [meta.trans.other] result_of
17 // tests.
18 
19 #include <type_traits>
20 #include <functional>
21 #include <memory>
22 
23 #include "test_macros.h"
24 
25 struct Tag {};
26 struct DerFromTag : Tag {};
27 
28 struct Implicit {
ImplicitImplicit29   Implicit(int) {}
30 };
31 
32 struct Explicit {
ExplicitExplicit33   explicit Explicit(int) {}
34 };
35 
36 struct NotCallableWithInt {
37   int operator()(int) = delete;
operator ()NotCallableWithInt38   int operator()(Tag) { return 42; }
39 };
40 
main()41 int main()
42 {
43     {
44         using Fn = int(Tag::*)(int);
45         using RFn = int(Tag::*)(int) &&;
46         // INVOKE bullet 1, 2 and 3
47         {
48             // Bullet 1
49             static_assert(std::is_invocable<Fn, Tag&, int>::value, "");
50             static_assert(std::is_invocable<Fn, DerFromTag&, int>::value, "");
51             static_assert(std::is_invocable<RFn, Tag&&, int>::value, "");
52             static_assert(!std::is_invocable<RFn, Tag&, int>::value, "");
53             static_assert(!std::is_invocable<Fn, Tag&>::value, "");
54             static_assert(!std::is_invocable<Fn, Tag const&, int>::value, "");
55         }
56         {
57             // Bullet 2
58             using T = std::reference_wrapper<Tag>;
59             using DT = std::reference_wrapper<DerFromTag>;
60             using CT = std::reference_wrapper<const Tag>;
61             static_assert(std::is_invocable<Fn, T&, int>::value, "");
62             static_assert(std::is_invocable<Fn, DT&, int>::value, "");
63             static_assert(std::is_invocable<Fn, const T&, int>::value, "");
64             static_assert(std::is_invocable<Fn, T&&, int>::value, "");
65             static_assert(!std::is_invocable<Fn, CT&, int>::value, "");
66             static_assert(!std::is_invocable<RFn, T, int>::value, "");
67         }
68         {
69             // Bullet 3
70             using T = Tag*;
71             using DT = DerFromTag*;
72             using CT = const Tag*;
73             using ST = std::unique_ptr<Tag>;
74             static_assert(std::is_invocable<Fn, T&, int>::value, "");
75             static_assert(std::is_invocable<Fn, DT&, int>::value, "");
76             static_assert(std::is_invocable<Fn, const T&, int>::value, "");
77             static_assert(std::is_invocable<Fn, T&&, int>::value, "");
78             static_assert(std::is_invocable<Fn, ST, int>::value, "");
79             static_assert(!std::is_invocable<Fn, CT&, int>::value, "");
80             static_assert(!std::is_invocable<RFn, T, int>::value, "");
81         }
82     }
83     {
84         // Bullets 4, 5 and 6
85         using Fn = int (Tag::*);
86         static_assert(!std::is_invocable<Fn>::value, "");
87         {
88             // Bullet 4
89             static_assert(std::is_invocable<Fn, Tag&>::value, "");
90             static_assert(std::is_invocable<Fn, DerFromTag&>::value, "");
91             static_assert(std::is_invocable<Fn, Tag&&>::value, "");
92             static_assert(std::is_invocable<Fn, Tag const&>::value, "");
93         }
94         {
95             // Bullet 5
96             using T = std::reference_wrapper<Tag>;
97             using DT = std::reference_wrapper<DerFromTag>;
98             using CT = std::reference_wrapper<const Tag>;
99             static_assert(std::is_invocable<Fn, T&>::value, "");
100             static_assert(std::is_invocable<Fn, DT&>::value, "");
101             static_assert(std::is_invocable<Fn, const T&>::value, "");
102             static_assert(std::is_invocable<Fn, T&&>::value, "");
103             static_assert(std::is_invocable<Fn, CT&>::value, "");
104         }
105         {
106             // Bullet 6
107             using T = Tag*;
108             using DT = DerFromTag*;
109             using CT = const Tag*;
110             using ST = std::unique_ptr<Tag>;
111             static_assert(std::is_invocable<Fn, T&>::value, "");
112             static_assert(std::is_invocable<Fn, DT&>::value, "");
113             static_assert(std::is_invocable<Fn, const T&>::value, "");
114             static_assert(std::is_invocable<Fn, T&&>::value, "");
115             static_assert(std::is_invocable<Fn, ST>::value, "");
116             static_assert(std::is_invocable<Fn, CT&>::value, "");
117         }
118     }
119     {
120         // INVOKE bullet 7
121         {
122             // Function pointer
123             using Fp = void(*)(Tag&, int);
124             static_assert(std::is_invocable<Fp, Tag&, int>::value, "");
125             static_assert(std::is_invocable<Fp, DerFromTag&, int>::value, "");
126             static_assert(!std::is_invocable<Fp, const Tag&, int>::value, "");
127             static_assert(!std::is_invocable<Fp>::value, "");
128             static_assert(!std::is_invocable<Fp, Tag&>::value, "");
129         }
130         {
131             // Function reference
132             using Fp = void(&)(Tag&, int);
133             static_assert(std::is_invocable<Fp, Tag&, int>::value, "");
134             static_assert(std::is_invocable<Fp, DerFromTag&, int>::value, "");
135             static_assert(!std::is_invocable<Fp, const Tag&, int>::value, "");
136             static_assert(!std::is_invocable<Fp>::value, "");
137             static_assert(!std::is_invocable<Fp, Tag&>::value, "");
138         }
139         {
140             // Function object
141             using Fn = NotCallableWithInt;
142             static_assert(std::is_invocable<Fn, Tag>::value, "");
143             static_assert(!std::is_invocable<Fn, int>::value, "");
144         }
145     }
146     {
147         // Check that the conversion to the return type is properly checked
148         using Fn = int(*)();
149         static_assert(std::is_invocable_r<Implicit, Fn>::value, "");
150         static_assert(std::is_invocable_r<double, Fn>::value, "");
151         static_assert(std::is_invocable_r<const volatile void, Fn>::value, "");
152         static_assert(!std::is_invocable_r<Explicit, Fn>::value, "");
153     }
154     {
155         // Check for is_invocable_v
156         using Fn = void(*)();
157         static_assert(std::is_invocable_v<Fn>, "");
158         static_assert(!std::is_invocable_v<Fn, int>, "");
159     }
160     {
161         // Check for is_invocable_r_v
162         using Fn = void(*)();
163         static_assert(std::is_invocable_r_v<void, Fn>, "");
164         static_assert(!std::is_invocable_r_v<int, Fn>, "");
165     }
166 }
167