• 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 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 }