blob: b6fe190bd2a773e1022c642d4f9f0b7633c70db2 [file] [log] [blame]
Eric Fiselier48aa2cf2015-07-28 01:25:36 +00001//===----------------------------------------------------------------------===//
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)
Dan Albert1d4a1ed2016-05-25 22:36:09 -070016// - Bullet 3 -- t1.*f
17// - Bullet 4 -- (*t1).*f
Eric Fiselier48aa2cf2015-07-28 01:25:36 +000018//
19// Overview:
Dan Albert1d4a1ed2016-05-25 22:36:09 -070020// 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.
Eric Fiselier48aa2cf2015-07-28 01:25:36 +000023//
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
41template <class Tp>
42struct TestMemberObject {
43 TestMemberObject() : object() {}
44 Tp object;
45private:
46 TestMemberObject(TestMemberObject const&);
47 TestMemberObject& operator=(TestMemberObject const&);
48};
49
50template <class ObjectType>
51struct TestCase {
52 public:
53
54 static void run() { TestCase().doTest(); }
55
56private:
57 typedef TestMemberObject<ObjectType> TestType;
58
59 //==========================================================================
60 // TEST DISPATCH
61 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);
Dan Albert1d4a1ed2016-05-25 22:36:09 -070077 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);
Eric Fiselier48aa2cf2015-07-28 01:25:36 +000080 }
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);
Dan Albert1d4a1ed2016-05-25 22:36:09 -070088 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);
Eric Fiselier48aa2cf2015-07-28 01:25:36 +000091 }
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);
Dan Albert1d4a1ed2016-05-25 22:36:09 -070099 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);
Eric Fiselier48aa2cf2015-07-28 01:25:36 +0000102 }
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);
Dan Albert1d4a1ed2016-05-25 22:36:09 -0700110 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);
Eric Fiselier48aa2cf2015-07-28 01:25:36 +0000113 }
114 }
115
116 template <class Expect, class Fn, class T>
117 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>
Dan Albert1d4a1ed2016-05-25 22:36:09 -0700131 void runTestPointerDispatch(Fn M, T& obj, ObjectType* expect) {
Eric Fiselier48aa2cf2015-07-28 01:25:36 +0000132 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
146 void runTest(Fn M, T&& obj, ObjectType* expect) {
147#else
148 void runTest(Fn M, T& obj, ObjectType* expect ) {
149#endif
Dan Albert1d4a1ed2016-05-25 22:36:09 -0700150 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);
Eric Fiselier48aa2cf2015-07-28 01:25:36 +0000155 }
156};
157
Eric Fiselier48aa2cf2015-07-28 01:25:36 +0000158int 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}