1 //===----------------------------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 // UNSUPPORTED: c++03, c++11, c++14
13 // ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_CXX20_REMOVED_TYPE_TRAITS
14 // ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DISABLE_DEPRECATION_WARNINGS
16 // template<class F, class... Args>
17 // invoke_result_t<F, Args...> invoke(F&& f, Args&&... args) // C++17
18 // noexcept(is_nothrow_invocable_v<_Fn, _Args...>);
20 /// C++14 [func.def] 20.9.0
21 /// (1) The following definitions apply to this Clause:
22 /// (2) A call signature is the name of a return type followed by a parenthesized
23 /// comma-separated list of zero or more argument types.
24 /// (3) A callable type is a function object type (20.9) or a pointer to member.
25 /// (4) A callable object is an object of a callable type.
26 /// (5) A call wrapper type is a type that holds a callable object and supports
27 /// a call operation that forwards to that object.
28 /// (6) A call wrapper is an object of a call wrapper type.
29 /// (7) A target object is the callable object held by a call wrapper.
31 /// C++14 [func.require] 20.9.1
33 /// Define INVOKE (f, t1, t2, ..., tN) as follows:
34 /// (1.1) - (t1.*f)(t2, ..., tN) when f is a pointer to a member function of a class T and t1 is an object of
35 /// type T or a reference to an object of type T or a reference to an object of a type derived from T;
36 /// (1.2) - ((*t1).*f)(t2, ..., tN) when f is a pointer to a member function of a class T and t1 is not one of
37 /// the types described in the previous item;
38 /// (1.3) - t1.*f when N == 1 and f is a pointer to member data of a class T and t1 is an object of type T or a
39 /// reference to an object of type T or a reference to an object of a type derived from T;
40 /// (1.4) - (*t1).*f when N == 1 and f is a pointer to member data of a class T and t1 is not one of the types
41 /// described in the previous item;
42 /// (1.5) - f(t1, t2, ..., tN) in all other cases.
45 #include <type_traits>
46 #include <utility> // for std::move
49 #include "test_macros.h"
54 NonCopyable(NonCopyable
const&) = delete;
55 NonCopyable
& operator=(NonCopyable
const&) = delete;
59 explicit TestClass(int x
) : data(x
) {}
61 int& operator()(NonCopyable
&&) & { return data
; }
62 int const& operator()(NonCopyable
&&) const & { return data
; }
63 int volatile& operator()(NonCopyable
&&) volatile & { return data
; }
64 int const volatile& operator()(NonCopyable
&&) const volatile & { return data
; }
66 int&& operator()(NonCopyable
&&) && { return std::move(data
); }
67 int const&& operator()(NonCopyable
&&) const && { return std::move(data
); }
68 int volatile&& operator()(NonCopyable
&&) volatile && { return std::move(data
); }
69 int const volatile&& operator()(NonCopyable
&&) const volatile && { return std::move(data
); }
73 TestClass(TestClass
const&) = delete;
74 TestClass
& operator=(TestClass
const&) = delete;
77 struct DerivedFromTestClass
: public TestClass
{
78 explicit DerivedFromTestClass(int x
) : TestClass(x
) {}
81 int& foo(NonCopyable
&&) {
86 template <class Signature
, class Expect
, class Functor
>
87 void test_b12(Functor
&& f
) {
88 // Create the callable object.
89 typedef Signature
TestClass::*ClassFunc
;
90 ClassFunc func_ptr
= &TestClass::operator();
92 // Create the dummy arg.
95 // Check that the deduced return type of invoke is what is expected.
97 std::invoke(func_ptr
, std::forward
<Functor
>(f
), std::move(arg
))
99 static_assert((std::is_same
<DeducedReturnType
, Expect
>::value
), "");
101 // Check that result_of_t matches Expect.
102 typedef typename
std::result_of
<ClassFunc
&&(Functor
&&, NonCopyable
&&)>::type
104 static_assert((std::is_same
<ResultOfReturnType
, Expect
>::value
), "");
106 // Run invoke and check the return value.
107 DeducedReturnType ret
=
108 std::invoke(func_ptr
, std::forward
<Functor
>(f
), std::move(arg
));
112 template <class Expect
, class Functor
>
113 void test_b34(Functor
&& f
) {
114 // Create the callable object.
115 typedef int TestClass::*ClassFunc
;
116 ClassFunc func_ptr
= &TestClass::data
;
118 // Check that the deduced return type of invoke is what is expected.
120 std::invoke(func_ptr
, std::forward
<Functor
>(f
))
122 static_assert((std::is_same
<DeducedReturnType
, Expect
>::value
), "");
124 // Check that result_of_t matches Expect.
125 typedef typename
std::result_of
<ClassFunc
&&(Functor
&&)>::type
127 static_assert((std::is_same
<ResultOfReturnType
, Expect
>::value
), "");
129 // Run invoke and check the return value.
130 DeducedReturnType ret
=
131 std::invoke(func_ptr
, std::forward
<Functor
>(f
));
135 template <class Expect
, class Functor
>
136 void test_b5(Functor
&& f
) {
139 // Check that the deduced return type of invoke is what is expected.
141 std::invoke(std::forward
<Functor
>(f
), std::move(arg
))
143 static_assert((std::is_same
<DeducedReturnType
, Expect
>::value
), "");
145 // Check that result_of_t matches Expect.
146 typedef typename
std::result_of
<Functor
&&(NonCopyable
&&)>::type
148 static_assert((std::is_same
<ResultOfReturnType
, Expect
>::value
), "");
150 // Run invoke and check the return value.
151 DeducedReturnType ret
= std::invoke(std::forward
<Functor
>(f
), std::move(arg
));
155 void bullet_one_two_tests() {
158 test_b12
<int&(NonCopyable
&&) &, int&>(cl
);
159 test_b12
<int const&(NonCopyable
&&) const &, int const&>(cl
);
160 test_b12
<int volatile&(NonCopyable
&&) volatile &, int volatile&>(cl
);
161 test_b12
<int const volatile&(NonCopyable
&&) const volatile &, int const volatile&>(cl
);
163 test_b12
<int&&(NonCopyable
&&) &&, int&&>(std::move(cl
));
164 test_b12
<int const&&(NonCopyable
&&) const &&, int const&&>(std::move(cl
));
165 test_b12
<int volatile&&(NonCopyable
&&) volatile &&, int volatile&&>(std::move(cl
));
166 test_b12
<int const volatile&&(NonCopyable
&&) const volatile &&, int const volatile&&>(std::move(cl
));
169 DerivedFromTestClass
cl(42);
170 test_b12
<int&(NonCopyable
&&) &, int&>(cl
);
171 test_b12
<int const&(NonCopyable
&&) const &, int const&>(cl
);
172 test_b12
<int volatile&(NonCopyable
&&) volatile &, int volatile&>(cl
);
173 test_b12
<int const volatile&(NonCopyable
&&) const volatile &, int const volatile&>(cl
);
175 test_b12
<int&&(NonCopyable
&&) &&, int&&>(std::move(cl
));
176 test_b12
<int const&&(NonCopyable
&&) const &&, int const&&>(std::move(cl
));
177 test_b12
<int volatile&&(NonCopyable
&&) volatile &&, int volatile&&>(std::move(cl
));
178 test_b12
<int const volatile&&(NonCopyable
&&) const volatile &&, int const volatile&&>(std::move(cl
));
181 TestClass
cl_obj(42);
182 std::reference_wrapper
<TestClass
> cl(cl_obj
);
183 test_b12
<int&(NonCopyable
&&) &, int&>(cl
);
184 test_b12
<int const&(NonCopyable
&&) const &, int const&>(cl
);
185 test_b12
<int volatile&(NonCopyable
&&) volatile &, int volatile&>(cl
);
186 test_b12
<int const volatile&(NonCopyable
&&) const volatile &, int const volatile&>(cl
);
188 test_b12
<int&(NonCopyable
&&) &, int&>(std::move(cl
));
189 test_b12
<int const&(NonCopyable
&&) const &, int const&>(std::move(cl
));
190 test_b12
<int volatile&(NonCopyable
&&) volatile &, int volatile&>(std::move(cl
));
191 test_b12
<int const volatile&(NonCopyable
&&) const volatile &, int const volatile&>(std::move(cl
));
194 DerivedFromTestClass
cl_obj(42);
195 std::reference_wrapper
<DerivedFromTestClass
> cl(cl_obj
);
196 test_b12
<int&(NonCopyable
&&) &, int&>(cl
);
197 test_b12
<int const&(NonCopyable
&&) const &, int const&>(cl
);
198 test_b12
<int volatile&(NonCopyable
&&) volatile &, int volatile&>(cl
);
199 test_b12
<int const volatile&(NonCopyable
&&) const volatile &, int const volatile&>(cl
);
201 test_b12
<int&(NonCopyable
&&) &, int&>(std::move(cl
));
202 test_b12
<int const&(NonCopyable
&&) const &, int const&>(std::move(cl
));
203 test_b12
<int volatile&(NonCopyable
&&) volatile &, int volatile&>(std::move(cl
));
204 test_b12
<int const volatile&(NonCopyable
&&) const volatile &, int const volatile&>(std::move(cl
));
207 TestClass
cl_obj(42);
208 TestClass
*cl
= &cl_obj
;
209 test_b12
<int&(NonCopyable
&&) &, int&>(cl
);
210 test_b12
<int const&(NonCopyable
&&) const &, int const&>(cl
);
211 test_b12
<int volatile&(NonCopyable
&&) volatile &, int volatile&>(cl
);
212 test_b12
<int const volatile&(NonCopyable
&&) const volatile &, int const volatile&>(cl
);
215 DerivedFromTestClass
cl_obj(42);
216 DerivedFromTestClass
*cl
= &cl_obj
;
217 test_b12
<int&(NonCopyable
&&) &, int&>(cl
);
218 test_b12
<int const&(NonCopyable
&&) const &, int const&>(cl
);
219 test_b12
<int volatile&(NonCopyable
&&) volatile &, int volatile&>(cl
);
220 test_b12
<int const volatile&(NonCopyable
&&) const volatile &, int const volatile&>(cl
);
224 void bullet_three_four_tests() {
226 typedef TestClass Fn
;
229 test_b34
<int const&>(static_cast<Fn
const&>(cl
));
230 test_b34
<int volatile&>(static_cast<Fn
volatile&>(cl
));
231 test_b34
<int const volatile&>(static_cast<Fn
const volatile &>(cl
));
233 test_b34
<int&&>(static_cast<Fn
&&>(cl
));
234 test_b34
<int const&&>(static_cast<Fn
const&&>(cl
));
235 test_b34
<int volatile&&>(static_cast<Fn
volatile&&>(cl
));
236 test_b34
<int const volatile&&>(static_cast<Fn
const volatile&&>(cl
));
239 typedef DerivedFromTestClass Fn
;
242 test_b34
<int const&>(static_cast<Fn
const&>(cl
));
243 test_b34
<int volatile&>(static_cast<Fn
volatile&>(cl
));
244 test_b34
<int const volatile&>(static_cast<Fn
const volatile &>(cl
));
246 test_b34
<int&&>(static_cast<Fn
&&>(cl
));
247 test_b34
<int const&&>(static_cast<Fn
const&&>(cl
));
248 test_b34
<int volatile&&>(static_cast<Fn
volatile&&>(cl
));
249 test_b34
<int const volatile&&>(static_cast<Fn
const volatile&&>(cl
));
252 typedef TestClass Fn
;
254 test_b34
<int&>(std::reference_wrapper
<Fn
>(cl
));
255 test_b34
<int const&>(std::reference_wrapper
<Fn
const>(cl
));
256 test_b34
<int volatile&>(std::reference_wrapper
<Fn
volatile>(cl
));
257 test_b34
<int const volatile&>(std::reference_wrapper
<Fn
const volatile>(cl
));
260 typedef DerivedFromTestClass Fn
;
262 test_b34
<int&>(std::reference_wrapper
<Fn
>(cl
));
263 test_b34
<int const&>(std::reference_wrapper
<Fn
const>(cl
));
264 test_b34
<int volatile&>(std::reference_wrapper
<Fn
volatile>(cl
));
265 test_b34
<int const volatile&>(std::reference_wrapper
<Fn
const volatile>(cl
));
268 typedef TestClass Fn
;
272 test_b34
<int const&>(static_cast<Fn
const*>(cl
));
273 test_b34
<int volatile&>(static_cast<Fn
volatile*>(cl
));
274 test_b34
<int const volatile&>(static_cast<Fn
const volatile *>(cl
));
277 typedef DerivedFromTestClass Fn
;
281 test_b34
<int const&>(static_cast<Fn
const*>(cl
));
282 test_b34
<int volatile&>(static_cast<Fn
volatile*>(cl
));
283 test_b34
<int const volatile&>(static_cast<Fn
const volatile *>(cl
));
287 void bullet_five_tests() {
288 using FooType
= int&(NonCopyable
&&);
298 typedef TestClass Fn
;
301 test_b5
<int const&>(static_cast<Fn
const&>(cl
));
302 test_b5
<int volatile&>(static_cast<Fn
volatile&>(cl
));
303 test_b5
<int const volatile&>(static_cast<Fn
const volatile &>(cl
));
305 test_b5
<int&&>(static_cast<Fn
&&>(cl
));
306 test_b5
<int const&&>(static_cast<Fn
const&&>(cl
));
307 test_b5
<int volatile&&>(static_cast<Fn
volatile&&>(cl
));
308 test_b5
<int const volatile&&>(static_cast<Fn
const volatile&&>(cl
));
314 CopyThrows(CopyThrows
const&) {}
315 CopyThrows(CopyThrows
&&) noexcept
{}
318 struct NoThrowCallable
{
319 void operator()() noexcept
{}
320 void operator()(CopyThrows
) noexcept
{}
323 struct ThrowsCallable
{
331 void noexcept_test() {
333 NoThrowCallable obj
; ((void)obj
); // suppress unused warning
334 CopyThrows arg
; ((void)arg
); // suppress unused warning
335 static_assert(noexcept(std::invoke(obj
)), "");
336 static_assert(!noexcept(std::invoke(obj
, arg
)), "");
337 static_assert(noexcept(std::invoke(obj
, std::move(arg
))), "");
340 ThrowsCallable obj
; ((void)obj
); // suppress unused warning
341 static_assert(!noexcept(std::invoke(obj
)), "");
344 MemberObj obj
{42}; ((void)obj
); // suppress unused warning.
345 static_assert(noexcept(std::invoke(&MemberObj::x
, obj
)), "");
349 // LWG3655: The INVOKE operation and union types
353 int f() { return 42; }
354 int g() const { return 52; }
357 // With a data member
359 auto get
= []() -> Union
{ return Union
{.x
= 3}; };
360 int result
= std::invoke(&Union::x
, get());
364 auto get
= []() -> Union
const { return Union
{.x
= 3}; };
365 int result
= std::invoke(&Union::x
, get());
370 int& result
= std::invoke(&Union::x
, u
);
371 assert(&result
== &u
.x
);
375 int const& result
= std::invoke(&Union::x
, u
);
376 assert(&result
== &u
.x
);
379 // With a pointer to a member function
381 auto get
= []() -> Union
{ return Union
{.x
= 3}; };
382 int result
= std::invoke(&Union::f
, get());
383 assert(result
== 42);
387 int result
= std::invoke(&Union::f
, u
);
388 assert(result
== 42);
391 // constness mismatch
392 static_assert(!std::is_invocable_v
<int (Union::*)(), Union
const>);
393 static_assert(!std::is_invocable_v
<int (Union::*)(), Union
const&>);
397 auto get
= []() -> Union
{ return Union
{.x
= 3}; };
398 int result
= std::invoke(&Union::g
, get());
399 assert(result
== 52);
402 auto get
= []() -> Union
const { return Union
{.x
= 3}; };
403 int result
= std::invoke(&Union::g
, get());
404 assert(result
== 52);
408 int result
= std::invoke(&Union::g
, u
);
409 assert(result
== 52);
413 int result
= std::invoke(&Union::g
, u
);
414 assert(result
== 52);
418 int main(int, char**) {
419 bullet_one_two_tests();
420 bullet_three_four_tests();