xref: /llvm-project/libcxx/test/libcxx/utilities/function.objects/func.require/bullet_4_5_6.pass.cpp (revision 09e3a360581dc36d0820d3fb6da9bd7cfed87b5d)
1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 // FIXME(EricWF): Make this test pass in C++03 with Clang once the transition
10 // has gotten far enough that __invoke works.
11 // XFAIL: c++03
12 
13 // <functional>
14 
15 // INVOKE (f, t1, t2, ..., tN)
16 
17 //------------------------------------------------------------------------------
18 // TESTING INVOKE(f, t1, t2, ..., tN)
19 //   - Bullet 4 -- t1.*f
20 //   - Bullet 5 -- t1.get().*f // t1 is a reference wrapper.
21 //   - Bullet 6 -- (*t1).*f
22 //
23 // Overview:
24 //    Bullets 4, 5 and 6 handle the case where 'f' is a pointer to member object.
25 //    Bullet 4 only handles the cases where t1 is an object of type T or a
26 //    type derived from 'T'. Bullet 5 handles cases where 't1' is a reference_wrapper
27 //     and bullet 6 handles all other cases.
28 //
29 // Concerns:
30 //   1) The return type is always an lvalue reference.
31 //   2) The return type is not less cv-qualified that the object that contains it.
32 //   3) The return type is not less cv-qualified than object type.
33 //   4) The call object is perfectly forwarded.
34 //   5) Classes that are publicly derived from 'T' are accepted as the call object
35 //   6) All types that dereference to T or a type derived from T can be used
36 //      as the call object.
37 //   7) Pointers to T or a type derived from T can be used as the call object.
38 //   8) reference_wrapper's are properly unwrapped before invoking the function.
39 
40 #include <functional>
41 #include <cassert>
42 #include <type_traits>
43 #include <utility>
44 
45 #include "test_macros.h"
46 #include "invoke_helpers.h"
47 
48 template <class Tp>
49 struct TestMemberObject {
50     TestMemberObject() : object() {}
51     Tp object;
52 private:
53     TestMemberObject(TestMemberObject const&);
54     TestMemberObject& operator=(TestMemberObject const&);
55 };
56 
57 template <class ObjectType>
58 struct TestCase {
59     public:
60 
61     static void run() { TestCase().doTest(); }
62 
63 private:
64     typedef TestMemberObject<ObjectType> TestType;
65 
66     //==========================================================================
67     // TEST DISPATCH
68     void doTest() {
69         typedef DerivedFromType<TestType> Derived;
70         TestType obj;
71         TestType* obj_ptr = &obj;
72         Derived der;
73         Derived* der_ptr = &der;
74         DerefToType<TestType>   dref;
75         DerefPropType<TestType> dref2;
76         std::reference_wrapper<TestType> rref(obj);
77         std::reference_wrapper<Derived> drref(der);
78 
79         {
80             typedef ObjectType (TestType::*MemPtr);
81             typedef ObjectType E;
82             MemPtr M = &TestType::object;
83             runTestDispatch<E>(M, obj, &obj.object);
84             runTestDispatch<E>(M, der, &der.object);
85             runTestDispatch<E>(M, dref2, &dref2.object.object);
86             runTestPropCVDispatch<E>(M, obj_ptr, &obj_ptr->object);
87             runTestPropCVDispatch<E>(M, der_ptr, &der_ptr->object);
88 #if TEST_STD_VER >= 11
89             runTestPropCVDispatch<E>(M, rref, &(rref.get().object));
90             runTestPropCVDispatch<E>(M, drref, &(drref.get().object));
91 #endif
92             runTestNoPropDispatch<E>(M, dref, &dref.object.object);
93         }
94         {
95             typedef ObjectType const (TestType::*CMemPtr);
96             typedef ObjectType const E;
97             CMemPtr M = &TestType::object;
98             runTestDispatch<E>(M, obj, &obj.object);
99             runTestDispatch<E>(M, der, &der.object);
100             runTestDispatch<E>(M, dref2, &dref2.object.object);
101             runTestPropCVDispatch<E>(M, obj_ptr, &obj_ptr->object);
102             runTestPropCVDispatch<E>(M, der_ptr, &der_ptr->object);
103 #if TEST_STD_VER >= 11
104             runTestPropCVDispatch<E>(M, rref, &(rref.get().object));
105             runTestPropCVDispatch<E>(M, drref, &(drref.get().object));
106 #endif
107             runTestNoPropDispatch<E>(M, dref,    &dref.object.object);
108         }
109         {
110             typedef ObjectType volatile (TestType::*VMemPtr);
111             typedef ObjectType volatile E;
112             VMemPtr M = &TestType::object;
113             runTestDispatch<E>(M, obj,  &obj.object);
114             runTestDispatch<E>(M, der,  &der.object);
115             runTestDispatch<E>(M, dref2, &dref2.object.object);
116             runTestPropCVDispatch<E>(M, obj_ptr, &obj_ptr->object);
117             runTestPropCVDispatch<E>(M, der_ptr, &der_ptr->object);
118 #if TEST_STD_VER >= 11
119             runTestPropCVDispatch<E>(M, rref, &(rref.get().object));
120             runTestPropCVDispatch<E>(M, drref, &(drref.get().object));
121 #endif
122             runTestNoPropDispatch<E>(M, dref,    &dref.object.object);
123         }
124         {
125             typedef ObjectType const volatile (TestType::*CVMemPtr);
126             typedef ObjectType const volatile E;
127             CVMemPtr M = &TestType::object;
128             runTestDispatch<E>(M, obj,   &obj.object);
129             runTestDispatch<E>(M, der,   &der.object);
130             runTestDispatch<E>(M, dref2, &dref2.object.object);
131             runTestPropCVDispatch<E>(M, obj_ptr, &obj_ptr->object);
132             runTestPropCVDispatch<E>(M, der_ptr, &der_ptr->object);
133 #if TEST_STD_VER >= 11
134             runTestPropCVDispatch<E>(M, rref, &(rref.get().object));
135             runTestPropCVDispatch<E>(M, drref, &(drref.get().object));
136 #endif
137             runTestNoPropDispatch<E>(M, dref,    &dref.object.object);
138         }
139     }
140 
141     template <class Expect, class Fn, class T>
142     void runTestDispatch(Fn M, T& obj, ObjectType* expect) {
143         runTest<Expect &>              (M, C_<T&>(obj),                expect);
144         runTest<Expect const&>         (M, C_<T const&>(obj),          expect);
145         runTest<Expect volatile&>      (M, C_<T volatile&>(obj),       expect);
146         runTest<Expect const volatile&>(M, C_<T const volatile&>(obj), expect);
147 #if TEST_STD_VER >= 11
148         runTest<Expect&&>               (M, C_<T&&>(obj),                expect);
149         runTest<Expect const&&>         (M, C_<T const&&>(obj),          expect);
150         runTest<Expect volatile&&>      (M, C_<T volatile&&>(obj),       expect);
151         runTest<Expect const volatile&&>(M, C_<T const volatile&&>(obj), expect);
152 #endif
153     }
154 
155     template <class Expect, class Fn, class T>
156     void runTestPropCVDispatch(Fn M, T& obj, ObjectType* expect) {
157         runTest<Expect &>              (M, obj,                     expect);
158         runTest<Expect const&>         (M, makeConst(obj),          expect);
159         runTest<Expect volatile&>      (M, makeVolatile(obj),       expect);
160         runTest<Expect const volatile&>(M, makeCV(obj),             expect);
161     }
162 
163     template <class Expect, class Fn, class T>
164     void runTestNoPropDispatch(Fn M, T& obj, ObjectType* expect) {
165         runTest<Expect&>(M, C_<T &>(obj),               expect);
166         runTest<Expect&>(M, C_<T const&>(obj),          expect);
167         runTest<Expect&>(M, C_<T volatile&>(obj),       expect);
168         runTest<Expect&>(M, C_<T const volatile&>(obj), expect);
169 #if TEST_STD_VER >= 11
170         runTest<Expect&>(M, C_<T&&>(obj),                expect);
171         runTest<Expect&>(M, C_<T const&&>(obj),          expect);
172         runTest<Expect&>(M, C_<T volatile&&>(obj),       expect);
173         runTest<Expect&>(M, C_<T const volatile&&>(obj), expect);
174 #endif
175     }
176 
177     template <class Expect, class Fn, class T>
178     void runTest(Fn M, const T& obj, ObjectType* expect) {
179          static_assert((std::is_same<
180             decltype(std::__invoke(M, obj)), Expect
181           >::value), "");
182         Expect e = std::__invoke(M, obj);
183         assert(&e == expect);
184     }
185 
186     template <class Expect, class Fn, class T>
187 #if TEST_STD_VER >= 11
188     void runTest(Fn M, T&& obj, ObjectType* expect) {
189 #else
190     void runTest(Fn M, T& obj, ObjectType* expect ) {
191 #endif
192         {
193             static_assert((std::is_same<
194                 decltype(std::__invoke(M, std::forward<T>(obj))), Expect
195               >::value), "");
196             Expect e = std::__invoke(M, std::forward<T>(obj));
197             assert(&e == expect);
198         }
199     }
200 };
201 
202 int main(int, char**) {
203     TestCase<ArgType>::run();
204     TestCase<ArgType const>::run();
205     TestCase<ArgType volatile>::run();
206     TestCase<ArgType const volatile>::run();
207     TestCase<ArgType*>::run();
208 
209   return 0;
210 }
211