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 // <functional>
11
12 // INVOKE (f, t1, t2, ..., tN)
13
14 //------------------------------------------------------------------------------
15 // TESTING INVOKE(f, t1, t2, ..., tN)
16 // - Bullet 4 -- t1.*f
17 // - Bullet 5 -- t1.get().*f // t1 is a reference wrapper.
18 // - Bullet 6 -- (*t1).*f
19 //
20 // Overview:
21 // Bullets 4, 5 and 6 handle the case where 'f' is a pointer to member object.
22 // Bullet 4 only handles the cases where t1 is an object of type T or a
23 // type derived from 'T'. Bullet 5 handles cases where 't1' is a reference_wrapper
24 // and bullet 6 handles all other cases.
25 //
26 // Concerns:
27 // 1) The return type is always an lvalue reference.
28 // 2) The return type is not less cv-qualified that the object that contains it.
29 // 3) The return type is not less cv-qualified than object type.
30 // 4) The call object is perfectly forwarded.
31 // 5) Classes that are publicly derived from 'T' are accepted as the call object
32 // 6) All types that dereference to T or a type derived from T can be used
33 // as the call object.
34 // 7) Pointers to T or a type derived from T can be used as the call object.
35 // 8) reference_wrapper's are properly unwrapped before invoking the function.
36
37 #include <functional>
38 #include <type_traits>
39 #include <cassert>
40
41 #include "test_macros.h"
42 #include "invoke_helpers.h"
43
44 template <class Tp>
45 struct TestMemberObject {
TestMemberObjectTestMemberObject46 TestMemberObject() : object() {}
47 Tp object;
48 private:
49 TestMemberObject(TestMemberObject const&);
50 TestMemberObject& operator=(TestMemberObject const&);
51 };
52
53 template <class ObjectType>
54 struct TestCase {
55 public:
56
runTestCase57 static void run() { TestCase().doTest(); }
58
59 private:
60 typedef TestMemberObject<ObjectType> TestType;
61
62 //==========================================================================
63 // TEST DISPATCH
doTestTestCase64 void doTest() {
65 typedef DerivedFromType<TestType> Derived;
66 TestType obj;
67 TestType* obj_ptr = &obj;
68 Derived der;
69 Derived* der_ptr = &der;
70 DerefToType<TestType> dref;
71 DerefPropType<TestType> dref2;
72 std::reference_wrapper<TestType> rref(obj);
73 std::reference_wrapper<Derived> drref(der);
74
75 {
76 typedef ObjectType (TestType::*MemPtr);
77 typedef ObjectType E;
78 MemPtr M = &TestType::object;
79 runTestDispatch<E>(M, obj, &obj.object);
80 runTestDispatch<E>(M, der, &der.object);
81 runTestDispatch<E>(M, dref2, &dref2.object.object);
82 runTestPropCVDispatch<E>(M, obj_ptr, &obj_ptr->object);
83 runTestPropCVDispatch<E>(M, der_ptr, &der_ptr->object);
84 #if TEST_STD_VER >= 11
85 runTestPropCVDispatch<E>(M, rref, &(rref.get().object));
86 runTestPropCVDispatch<E>(M, drref, &(drref.get().object));
87 #endif
88 runTestNoPropDispatch<E>(M, dref, &dref.object.object);
89 }
90 {
91 typedef ObjectType const (TestType::*CMemPtr);
92 typedef ObjectType const E;
93 CMemPtr M = &TestType::object;
94 runTestDispatch<E>(M, obj, &obj.object);
95 runTestDispatch<E>(M, der, &der.object);
96 runTestDispatch<E>(M, dref2, &dref2.object.object);
97 runTestPropCVDispatch<E>(M, obj_ptr, &obj_ptr->object);
98 runTestPropCVDispatch<E>(M, der_ptr, &der_ptr->object);
99 #if TEST_STD_VER >= 11
100 runTestPropCVDispatch<E>(M, rref, &(rref.get().object));
101 runTestPropCVDispatch<E>(M, drref, &(drref.get().object));
102 #endif
103 runTestNoPropDispatch<E>(M, dref, &dref.object.object);
104 }
105 {
106 typedef ObjectType volatile (TestType::*VMemPtr);
107 typedef ObjectType volatile E;
108 VMemPtr M = &TestType::object;
109 runTestDispatch<E>(M, obj, &obj.object);
110 runTestDispatch<E>(M, der, &der.object);
111 runTestDispatch<E>(M, dref2, &dref2.object.object);
112 runTestPropCVDispatch<E>(M, obj_ptr, &obj_ptr->object);
113 runTestPropCVDispatch<E>(M, der_ptr, &der_ptr->object);
114 #if TEST_STD_VER >= 11
115 runTestPropCVDispatch<E>(M, rref, &(rref.get().object));
116 runTestPropCVDispatch<E>(M, drref, &(drref.get().object));
117 #endif
118 runTestNoPropDispatch<E>(M, dref, &dref.object.object);
119 }
120 {
121 typedef ObjectType const volatile (TestType::*CVMemPtr);
122 typedef ObjectType const volatile E;
123 CVMemPtr M = &TestType::object;
124 runTestDispatch<E>(M, obj, &obj.object);
125 runTestDispatch<E>(M, der, &der.object);
126 runTestDispatch<E>(M, dref2, &dref2.object.object);
127 runTestPropCVDispatch<E>(M, obj_ptr, &obj_ptr->object);
128 runTestPropCVDispatch<E>(M, der_ptr, &der_ptr->object);
129 #if TEST_STD_VER >= 11
130 runTestPropCVDispatch<E>(M, rref, &(rref.get().object));
131 runTestPropCVDispatch<E>(M, drref, &(drref.get().object));
132 #endif
133 runTestNoPropDispatch<E>(M, dref, &dref.object.object);
134 }
135 }
136
137 template <class Expect, class Fn, class T>
runTestDispatchTestCase138 void runTestDispatch(Fn M, T& obj, ObjectType* expect) {
139 runTest<Expect &> (M, C_<T&>(obj), expect);
140 runTest<Expect const&> (M, C_<T const&>(obj), expect);
141 runTest<Expect volatile&> (M, C_<T volatile&>(obj), expect);
142 runTest<Expect const volatile&>(M, C_<T const volatile&>(obj), expect);
143 #if TEST_STD_VER >= 11
144 runTest<Expect&&> (M, C_<T&&>(obj), expect);
145 runTest<Expect const&&> (M, C_<T const&&>(obj), expect);
146 runTest<Expect volatile&&> (M, C_<T volatile&&>(obj), expect);
147 runTest<Expect const volatile&&>(M, C_<T const volatile&&>(obj), expect);
148 #endif
149 }
150
151 template <class Expect, class Fn, class T>
runTestPropCVDispatchTestCase152 void runTestPropCVDispatch(Fn M, T& obj, ObjectType* expect) {
153 runTest<Expect &> (M, obj, expect);
154 runTest<Expect const&> (M, makeConst(obj), expect);
155 runTest<Expect volatile&> (M, makeVolatile(obj), expect);
156 runTest<Expect const volatile&>(M, makeCV(obj), expect);
157 }
158
159 template <class Expect, class Fn, class T>
runTestNoPropDispatchTestCase160 void runTestNoPropDispatch(Fn M, T& obj, ObjectType* expect) {
161 runTest<Expect&>(M, C_<T &>(obj), expect);
162 runTest<Expect&>(M, C_<T const&>(obj), expect);
163 runTest<Expect&>(M, C_<T volatile&>(obj), expect);
164 runTest<Expect&>(M, C_<T const volatile&>(obj), expect);
165 #if TEST_STD_VER >= 11
166 runTest<Expect&>(M, C_<T&&>(obj), expect);
167 runTest<Expect&>(M, C_<T const&&>(obj), expect);
168 runTest<Expect&>(M, C_<T volatile&&>(obj), expect);
169 runTest<Expect&>(M, C_<T const volatile&&>(obj), expect);
170 #endif
171 }
172
173 template <class Expect, class Fn, class T>
runTestTestCase174 void runTest(Fn M, const T& obj, ObjectType* expect) {
175 static_assert((std::is_same<
176 decltype(std::__invoke(M, obj)), Expect
177 >::value), "");
178 Expect e = std::__invoke(M, obj);
179 assert(&e == expect);
180 }
181
182 template <class Expect, class Fn, class T>
183 #if TEST_STD_VER >= 11
runTestTestCase184 void runTest(Fn M, T&& obj, ObjectType* expect) {
185 #else
186 void runTest(Fn M, T& obj, ObjectType* expect ) {
187 #endif
188 {
189 static_assert((std::is_same<
190 decltype(std::__invoke(M, std::forward<T>(obj))), Expect
191 >::value), "");
192 Expect e = std::__invoke(M, std::forward<T>(obj));
193 assert(&e == expect);
194 }
195 #if TEST_STD_VER >= 11
196 {
197 static_assert((std::is_same<
198 decltype(std::__invoke_constexpr(M, std::forward<T>(obj))), Expect
199 >::value), "");
200 Expect e = std::__invoke_constexpr(M, std::forward<T>(obj));
201 assert(&e == expect);
202 }
203 #endif
204 }
205 };
206
207
208
209
main()210 int main() {
211 TestCase<ArgType>::run();
212 TestCase<ArgType const>::run();
213 TestCase<ArgType volatile>::run();
214 TestCase<ArgType const volatile>::run();
215 TestCase<ArgType*>::run();
216 }
217