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