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, c++17
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 // constexpr // constexpr in C++20
18 // invoke_result_t<F, Args...> invoke(F&& f, Args&&... args)
19 // noexcept(is_nothrow_invocable_v<_Fn, _Args...>);
21 /// C++14 [func.def] 20.9.0
22 /// (1) The following definitions apply to this Clause:
23 /// (2) A call signature is the name of a return type followed by a parenthesized
24 /// comma-separated list of zero or more argument types.
25 /// (3) A callable type is a function object type (20.9) or a pointer to member.
26 /// (4) A callable object is an object of a callable type.
27 /// (5) A call wrapper type is a type that holds a callable object and supports
28 /// a call operation that forwards to that object.
29 /// (6) A call wrapper is an object of a call wrapper type.
30 /// (7) A target object is the callable object held by a call wrapper.
32 /// C++14 [func.require] 20.9.1
34 /// Define INVOKE (f, t1, t2, ..., tN) as follows:
35 /// (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
36 /// type T or a reference to an object of type T or a reference to an object of a type derived from T;
37 /// (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
38 /// the types described in the previous item;
39 /// (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
40 /// reference to an object of type T or a reference to an object of a type derived from T;
41 /// (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
42 /// described in the previous item;
43 /// (1.5) - f(t1, t2, ..., tN) in all other cases.
46 #include <type_traits>
47 #include <utility> // for std::move
50 #include "test_macros.h"
53 constexpr NonCopyable() {}
55 NonCopyable(NonCopyable
const&) = delete;
56 NonCopyable
& operator=(NonCopyable
const&) = delete;
60 constexpr explicit TestClass(int x
) : data(x
) {}
62 constexpr int& operator()(NonCopyable
&&) & { return data
; }
63 constexpr int const& operator()(NonCopyable
&&) const & { return data
; }
65 constexpr int&& operator()(NonCopyable
&&) && { return std::move(data
); }
66 constexpr int const&& operator()(NonCopyable
&&) const && { return std::move(data
); }
70 TestClass(TestClass
const&) = delete;
71 TestClass
& operator=(TestClass
const&) = delete;
74 struct DerivedFromTestClass
: public TestClass
{
75 constexpr explicit DerivedFromTestClass(int x
) : TestClass(x
) {}
78 static constexpr int data
= 42;
79 constexpr const int& foo(NonCopyable
&&) {
83 template <class Signature
, class Expect
, class Functor
>
84 constexpr void test_b12(Functor
&& f
) {
85 // Create the callable object.
86 typedef Signature
TestClass::*ClassFunc
;
87 ClassFunc func_ptr
= &TestClass::operator();
89 // Create the dummy arg.
92 // Check that the deduced return type of invoke is what is expected.
94 std::invoke(func_ptr
, std::forward
<Functor
>(f
), std::move(arg
))
96 static_assert((std::is_same
<DeducedReturnType
, Expect
>::value
), "");
98 // Check that result_of_t matches Expect.
99 typedef typename
std::result_of
<ClassFunc
&&(Functor
&&, NonCopyable
&&)>::type
101 static_assert((std::is_same
<ResultOfReturnType
, Expect
>::value
), "");
103 // Run invoke and check the return value.
104 DeducedReturnType ret
=
105 std::invoke(func_ptr
, std::forward
<Functor
>(f
), std::move(arg
));
109 template <class Expect
, class Functor
>
110 constexpr void test_b34(Functor
&& f
) {
111 // Create the callable object.
112 typedef int TestClass::*ClassFunc
;
113 ClassFunc func_ptr
= &TestClass::data
;
115 // Check that the deduced return type of invoke is what is expected.
117 std::invoke(func_ptr
, std::forward
<Functor
>(f
))
119 static_assert((std::is_same
<DeducedReturnType
, Expect
>::value
), "");
121 // Check that result_of_t matches Expect.
122 typedef typename
std::result_of
<ClassFunc
&&(Functor
&&)>::type
124 static_assert((std::is_same
<ResultOfReturnType
, Expect
>::value
), "");
126 // Run invoke and check the return value.
127 DeducedReturnType ret
=
128 std::invoke(func_ptr
, std::forward
<Functor
>(f
));
132 template <class Expect
, class Functor
>
133 constexpr void test_b5(Functor
&& f
) {
136 // Check that the deduced return type of invoke is what is expected.
138 std::invoke(std::forward
<Functor
>(f
), std::move(arg
))
140 static_assert((std::is_same
<DeducedReturnType
, Expect
>::value
), "");
142 // Check that result_of_t matches Expect.
143 typedef typename
std::result_of
<Functor
&&(NonCopyable
&&)>::type
145 static_assert((std::is_same
<ResultOfReturnType
, Expect
>::value
), "");
147 // Run invoke and check the return value.
148 DeducedReturnType ret
= std::invoke(std::forward
<Functor
>(f
), std::move(arg
));
152 constexpr bool bullet_one_two_tests() {
155 test_b12
<int&(NonCopyable
&&) &, int&>(cl
);
156 test_b12
<int const&(NonCopyable
&&) const &, int const&>(cl
);
158 test_b12
<int&&(NonCopyable
&&) &&, int&&>(std::move(cl
));
159 test_b12
<int const&&(NonCopyable
&&) const &&, int const&&>(std::move(cl
));
162 DerivedFromTestClass
cl(42);
163 test_b12
<int&(NonCopyable
&&) &, int&>(cl
);
164 test_b12
<int const&(NonCopyable
&&) const &, int const&>(cl
);
166 test_b12
<int&&(NonCopyable
&&) &&, int&&>(std::move(cl
));
167 test_b12
<int const&&(NonCopyable
&&) const &&, int const&&>(std::move(cl
));
170 TestClass
cl_obj(42);
171 std::reference_wrapper
<TestClass
> cl(cl_obj
);
172 test_b12
<int&(NonCopyable
&&) &, int&>(cl
);
173 test_b12
<int const&(NonCopyable
&&) const &, int const&>(cl
);
175 test_b12
<int&(NonCopyable
&&) &, int&>(std::move(cl
));
176 test_b12
<int const&(NonCopyable
&&) const &, int const&>(std::move(cl
));
179 DerivedFromTestClass
cl_obj(42);
180 std::reference_wrapper
<DerivedFromTestClass
> cl(cl_obj
);
181 test_b12
<int&(NonCopyable
&&) &, int&>(cl
);
182 test_b12
<int const&(NonCopyable
&&) const &, int const&>(cl
);
184 test_b12
<int&(NonCopyable
&&) &, int&>(std::move(cl
));
185 test_b12
<int const&(NonCopyable
&&) const &, int const&>(std::move(cl
));
188 TestClass
cl_obj(42);
189 TestClass
*cl
= &cl_obj
;
190 test_b12
<int&(NonCopyable
&&) &, int&>(cl
);
191 test_b12
<int const&(NonCopyable
&&) const &, int const&>(cl
);
194 DerivedFromTestClass
cl_obj(42);
195 DerivedFromTestClass
*cl
= &cl_obj
;
196 test_b12
<int&(NonCopyable
&&) &, int&>(cl
);
197 test_b12
<int const&(NonCopyable
&&) const &, int const&>(cl
);
202 constexpr bool bullet_three_four_tests() {
204 typedef TestClass Fn
;
207 test_b34
<int const&>(static_cast<Fn
const&>(cl
));
209 test_b34
<int&&>(static_cast<Fn
&&>(cl
));
210 test_b34
<int const&&>(static_cast<Fn
const&&>(cl
));
213 typedef DerivedFromTestClass Fn
;
216 test_b34
<int const&>(static_cast<Fn
const&>(cl
));
218 test_b34
<int&&>(static_cast<Fn
&&>(cl
));
219 test_b34
<int const&&>(static_cast<Fn
const&&>(cl
));
222 typedef TestClass Fn
;
224 test_b34
<int&>(std::reference_wrapper
<Fn
>(cl
));
225 test_b34
<int const&>(std::reference_wrapper
<Fn
const>(cl
));
228 typedef DerivedFromTestClass Fn
;
230 test_b34
<int&>(std::reference_wrapper
<Fn
>(cl
));
231 test_b34
<int const&>(std::reference_wrapper
<Fn
const>(cl
));
234 typedef TestClass Fn
;
238 test_b34
<int const&>(static_cast<Fn
const*>(cl
));
241 typedef DerivedFromTestClass Fn
;
245 test_b34
<int const&>(static_cast<Fn
const*>(cl
));
250 constexpr bool bullet_five_tests() {
251 using FooType
= const int&(NonCopyable
&&);
254 test_b5
<const int &>(fn
);
258 test_b5
<const int &>(fn
);
261 typedef TestClass Fn
;
264 test_b5
<int const&>(static_cast<Fn
const&>(cl
));
266 test_b5
<int&&>(static_cast<Fn
&&>(cl
));
267 test_b5
<int const&&>(static_cast<Fn
const&&>(cl
));
272 int main(int, char**) {
273 bullet_one_two_tests();
274 bullet_three_four_tests();
277 static_assert(bullet_one_two_tests());
278 static_assert(bullet_three_four_tests());
279 static_assert(bullet_five_tests());