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
44template <class Tp>
45struct TestMemberObject {
46    TestMemberObject() : object() {}
47    Tp object;
48private:
49    TestMemberObject(TestMemberObject const&);
50    TestMemberObject& operator=(TestMemberObject const&);
51};
52
53template <class ObjectType>
54struct TestCase {
55    public:
56
57    static void run() { TestCase().doTest(); }
58
59private:
60    typedef TestMemberObject<ObjectType> TestType;
61
62    //==========================================================================
63    // TEST DISPATCH
64    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>
138    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>
152    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>
160    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>
174    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
184    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
210int 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