• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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