179 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9// FIXME(EricWF): Make this test pass in C++03 with Clang once the transition10// has gotten far enough that __invoke works.11// XFAIL: c++0312 13// <functional>14 15// INVOKE (f, t1, t2, ..., tN)16 17//------------------------------------------------------------------------------18// TESTING INVOKE(f, t1, t2, ..., tN)19// - Bullet 4 -- t1.*f20// - Bullet 5 -- t1.get().*f // t1 is a reference wrapper.21// - Bullet 6 -- (*t1).*f22//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 a26// type derived from 'T'. Bullet 5 handles cases where 't1' is a reference_wrapper27// 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 object35// 6) All types that dereference to T or a type derived from T can be used36// 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 48template <class Tp>49struct TestMemberObject {50 TestMemberObject() : object() {}51 Tp object;52private:53 TestMemberObject(TestMemberObject const&);54 TestMemberObject& operator=(TestMemberObject const&);55};56 57template <class ObjectType>58struct TestCase {59 public:60 61 static void run() { TestCase().doTest(); }62 63private:64 typedef TestMemberObject<ObjectType> TestType;65 66 //==========================================================================67 // TEST DISPATCH68 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 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 runTestNoPropDispatch<E>(M, dref, &dref.object.object);100 }101 {102 typedef ObjectType volatile (TestType::*VMemPtr);103 typedef ObjectType volatile E;104 VMemPtr M = &TestType::object;105 runTestDispatch<E>(M, obj, &obj.object);106 runTestDispatch<E>(M, der, &der.object);107 runTestDispatch<E>(M, dref2, &dref2.object.object);108 runTestPropCVDispatch<E>(M, obj_ptr, &obj_ptr->object);109 runTestPropCVDispatch<E>(M, der_ptr, &der_ptr->object);110 runTestNoPropDispatch<E>(M, dref, &dref.object.object);111 }112 {113 typedef ObjectType const volatile (TestType::*CVMemPtr);114 typedef ObjectType const volatile E;115 CVMemPtr M = &TestType::object;116 runTestDispatch<E>(M, obj, &obj.object);117 runTestDispatch<E>(M, der, &der.object);118 runTestDispatch<E>(M, dref2, &dref2.object.object);119 runTestPropCVDispatch<E>(M, obj_ptr, &obj_ptr->object);120 runTestPropCVDispatch<E>(M, der_ptr, &der_ptr->object);121 runTestNoPropDispatch<E>(M, dref, &dref.object.object);122 }123 }124 125 template <class Expect, class Fn, class T>126 void runTestDispatch(Fn M, T& obj, ObjectType* expect) {127 runTest<Expect &> (M, C_<T&>(obj), expect);128 runTest<Expect const&> (M, C_<T const&>(obj), expect);129 runTest<Expect volatile&> (M, C_<T volatile&>(obj), expect);130 runTest<Expect const volatile&>(M, C_<T const volatile&>(obj), expect);131 }132 133 template <class Expect, class Fn, class T>134 void runTestPropCVDispatch(Fn M, T& obj, ObjectType* expect) {135 runTest<Expect &> (M, obj, expect);136 runTest<Expect const&> (M, makeConst(obj), expect);137 runTest<Expect volatile&> (M, makeVolatile(obj), expect);138 runTest<Expect const volatile&>(M, makeCV(obj), expect);139 }140 141 template <class Expect, class Fn, class T>142 void runTestNoPropDispatch(Fn M, T& obj, ObjectType* expect) {143 runTest<Expect&>(M, C_<T &>(obj), expect);144 runTest<Expect&>(M, C_<T const&>(obj), expect);145 runTest<Expect&>(M, C_<T volatile&>(obj), expect);146 runTest<Expect&>(M, C_<T const volatile&>(obj), expect);147 }148 149 template <class Expect, class Fn, class T>150 void runTest(Fn M, const T& obj, ObjectType* expect) {151 static_assert((std::is_same<152 decltype(std::__invoke(M, obj)), Expect153 >::value), "");154 Expect e = std::__invoke(M, obj);155 assert(&e == expect);156 }157 158 template <class Expect, class Fn, class T>159 void runTest(Fn M, T& obj, ObjectType* expect ) {160 {161 static_assert((std::is_same<162 decltype(std::__invoke(M, std::forward<T>(obj))), Expect163 >::value), "");164 Expect e = std::__invoke(M, std::forward<T>(obj));165 assert(&e == expect);166 }167 }168};169 170int main(int, char**) {171 TestCase<ArgType>::run();172 TestCase<ArgType const>::run();173 TestCase<ArgType volatile>::run();174 TestCase<ArgType const volatile>::run();175 TestCase<ArgType*>::run();176 177 return 0;178}179