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 3 -- t1.*f
17 // - Bullet 4 -- (*t1).*f
18 //
19 // Overview:
20 // Bullets 3 and 4 handle the case where 'f' is a pointer to member object.
21 // Bullet 3 only handles the cases where t1 is an object of type T or a
22 // type derived from 'T'. Bullet 4 handles all other cases.
23 //
24 // Concerns:
25 // 1) The return type is always an lvalue reference.
26 // 2) The return type is not less cv-qualified that the object that contains it.
27 // 3) The return type is not less cv-qualified than object type.
28 // 4) The call object is perfectly forwarded.
29 // 5) Classes that are publicly derived from 'T' are accepted as the call object
30 // 6) All types that dereference to T or a type derived from T can be used
31 // as the call object.
32 // 7) Pointers to T or a type derived from T can be used as the call object.
33
34 #include <functional>
35 #include <type_traits>
36 #include <cassert>
37
38 #include "test_macros.h"
39 #include "invoke_helpers.h"
40
41 template <class Tp>
42 struct TestMemberObject {
TestMemberObjectTestMemberObject43 TestMemberObject() : object() {}
44 Tp object;
45 private:
46 TestMemberObject(TestMemberObject const&);
47 TestMemberObject& operator=(TestMemberObject const&);
48 };
49
50 template <class ObjectType>
51 struct TestCase {
52 public:
53
runTestCase54 static void run() { TestCase().doTest(); }
55
56 private:
57 typedef TestMemberObject<ObjectType> TestType;
58
59 //==========================================================================
60 // TEST DISPATCH
doTestTestCase61 void doTest() {
62 typedef DerivedFromType<TestType> Derived;
63 TestType obj;
64 TestType* obj_ptr = &obj;
65 Derived der;
66 Derived* der_ptr = &der;
67 DerefToType<TestType> dref;
68 DerefPropType<TestType> dref2;
69
70 {
71 typedef ObjectType (TestType::*MemPtr);
72 typedef ObjectType E;
73 MemPtr M = &TestType::object;
74 runTestDispatch<E>(M, obj, &obj.object);
75 runTestDispatch<E>(M, der, &der.object);
76 runTestDispatch<E>(M, dref2, &dref2.object.object);
77 runTestPointerDispatch<E>(M, obj_ptr, &obj_ptr->object);
78 runTestPointerDispatch<E>(M, der_ptr, &der_ptr->object);
79 runTestPointerDispatch<E>(M, dref, &dref.object.object);
80 }
81 {
82 typedef ObjectType const (TestType::*CMemPtr);
83 typedef ObjectType const E;
84 CMemPtr M = &TestType::object;
85 runTestDispatch<E>(M, obj, &obj.object);
86 runTestDispatch<E>(M, der, &der.object);
87 runTestDispatch<E>(M, dref2, &dref2.object.object);
88 runTestPointerDispatch<E>(M, obj_ptr, &obj_ptr->object);
89 runTestPointerDispatch<E>(M, der_ptr, &der_ptr->object);
90 runTestPointerDispatch<E>(M, dref, &dref.object.object);
91 }
92 {
93 typedef ObjectType volatile (TestType::*VMemPtr);
94 typedef ObjectType volatile E;
95 VMemPtr M = &TestType::object;
96 runTestDispatch<E>(M, obj, &obj.object);
97 runTestDispatch<E>(M, der, &der.object);
98 runTestDispatch<E>(M, dref2, &dref2.object.object);
99 runTestPointerDispatch<E>(M, obj_ptr, &obj_ptr->object);
100 runTestPointerDispatch<E>(M, der_ptr, &der_ptr->object);
101 runTestPointerDispatch<E>(M, dref, &dref.object.object);
102 }
103 {
104 typedef ObjectType const volatile (TestType::*CVMemPtr);
105 typedef ObjectType const volatile E;
106 CVMemPtr M = &TestType::object;
107 runTestDispatch<E>(M, obj, &obj.object);
108 runTestDispatch<E>(M, der, &der.object);
109 runTestDispatch<E>(M, dref2, &dref2.object.object);
110 runTestPointerDispatch<E>(M, obj_ptr, &obj_ptr->object);
111 runTestPointerDispatch<E>(M, der_ptr, &der_ptr->object);
112 runTestPointerDispatch<E>(M, dref, &dref.object.object);
113 }
114 }
115
116 template <class Expect, class Fn, class T>
runTestDispatchTestCase117 void runTestDispatch(Fn M, T& obj, ObjectType* expect) {
118 runTest<Expect &> (M, C_<T&>(obj), expect);
119 runTest<Expect const&> (M, C_<T const&>(obj), expect);
120 runTest<Expect volatile&> (M, C_<T volatile&>(obj), expect);
121 runTest<Expect const volatile&>(M, C_<T const volatile&>(obj), expect);
122 #if TEST_STD_VER >= 11
123 runTest<Expect&&> (M, C_<T&&>(obj), expect);
124 runTest<Expect const&&> (M, C_<T const&&>(obj), expect);
125 runTest<Expect volatile&&> (M, C_<T volatile&&>(obj), expect);
126 runTest<Expect const volatile&&>(M, C_<T const volatile&&>(obj), expect);
127 #endif
128 }
129
130 template <class Expect, class Fn, class T>
runTestPointerDispatchTestCase131 void runTestPointerDispatch(Fn M, T& obj, ObjectType* expect) {
132 runTest<Expect&>(M, C_<T &>(obj), expect);
133 runTest<Expect&>(M, C_<T const&>(obj), expect);
134 runTest<Expect&>(M, C_<T volatile&>(obj), expect);
135 runTest<Expect&>(M, C_<T const volatile&>(obj), expect);
136 #if TEST_STD_VER >= 11
137 runTest<Expect&>(M, C_<T&&>(obj), expect);
138 runTest<Expect&>(M, C_<T const&&>(obj), expect);
139 runTest<Expect&>(M, C_<T volatile&&>(obj), expect);
140 runTest<Expect&>(M, C_<T const volatile&&>(obj), expect);
141 #endif
142 }
143
144 template <class Expect, class Fn, class T>
145 #if TEST_STD_VER >= 11
runTestTestCase146 void runTest(Fn M, T&& obj, ObjectType* expect) {
147 #else
148 void runTest(Fn M, T& obj, ObjectType* expect ) {
149 #endif
150 static_assert((std::is_same<
151 decltype(std::__invoke(M, std::forward<T>(obj))), Expect
152 >::value), "");
153 Expect e = std::__invoke(M, std::forward<T>(obj));
154 assert(&e == expect);
155 }
156 };
157
main()158 int main() {
159 TestCase<ArgType>::run();
160 TestCase<ArgType const>::run();
161 TestCase<ArgType volatile>::run();
162 TestCase<ArgType const volatile>::run();
163 TestCase<ArgType*>::run();
164 }