//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // FIXME(EricWF): Make this test pass in C++03 with Clang once the transition // has gotten far enough that __invoke works. // XFAIL: c++03 // // INVOKE (f, t1, t2, ..., tN) //------------------------------------------------------------------------------ // TESTING INVOKE(f, t1, t2, ..., tN) // - Bullet 4 -- t1.*f // - Bullet 5 -- t1.get().*f // t1 is a reference wrapper. // - Bullet 6 -- (*t1).*f // // Overview: // Bullets 4, 5 and 6 handle the case where 'f' is a pointer to member object. // Bullet 4 only handles the cases where t1 is an object of type T or a // type derived from 'T'. Bullet 5 handles cases where 't1' is a reference_wrapper // and bullet 6 handles all other cases. // // Concerns: // 1) The return type is always an lvalue reference. // 2) The return type is not less cv-qualified that the object that contains it. // 3) The return type is not less cv-qualified than object type. // 4) The call object is perfectly forwarded. // 5) Classes that are publicly derived from 'T' are accepted as the call object // 6) All types that dereference to T or a type derived from T can be used // as the call object. // 7) Pointers to T or a type derived from T can be used as the call object. // 8) reference_wrapper's are properly unwrapped before invoking the function. #include #include #include #include #include "test_macros.h" #include "invoke_helpers.h" template struct TestMemberObject { TestMemberObject() : object() {} Tp object; private: TestMemberObject(TestMemberObject const&); TestMemberObject& operator=(TestMemberObject const&); }; template struct TestCase { public: static void run() { TestCase().doTest(); } private: typedef TestMemberObject TestType; //========================================================================== // TEST DISPATCH void doTest() { typedef DerivedFromType Derived; TestType obj; TestType* obj_ptr = &obj; Derived der; Derived* der_ptr = &der; DerefToType dref; DerefPropType dref2; std::reference_wrapper rref(obj); std::reference_wrapper drref(der); { typedef ObjectType (TestType::*MemPtr); typedef ObjectType E; MemPtr M = &TestType::object; runTestDispatch(M, obj, &obj.object); runTestDispatch(M, der, &der.object); runTestDispatch(M, dref2, &dref2.object.object); runTestPropCVDispatch(M, obj_ptr, &obj_ptr->object); runTestPropCVDispatch(M, der_ptr, &der_ptr->object); runTestNoPropDispatch(M, dref, &dref.object.object); } { typedef ObjectType const (TestType::*CMemPtr); typedef ObjectType const E; CMemPtr M = &TestType::object; runTestDispatch(M, obj, &obj.object); runTestDispatch(M, der, &der.object); runTestDispatch(M, dref2, &dref2.object.object); runTestPropCVDispatch(M, obj_ptr, &obj_ptr->object); runTestPropCVDispatch(M, der_ptr, &der_ptr->object); runTestNoPropDispatch(M, dref, &dref.object.object); } { typedef ObjectType volatile (TestType::*VMemPtr); typedef ObjectType volatile E; VMemPtr M = &TestType::object; runTestDispatch(M, obj, &obj.object); runTestDispatch(M, der, &der.object); runTestDispatch(M, dref2, &dref2.object.object); runTestPropCVDispatch(M, obj_ptr, &obj_ptr->object); runTestPropCVDispatch(M, der_ptr, &der_ptr->object); runTestNoPropDispatch(M, dref, &dref.object.object); } { typedef ObjectType const volatile (TestType::*CVMemPtr); typedef ObjectType const volatile E; CVMemPtr M = &TestType::object; runTestDispatch(M, obj, &obj.object); runTestDispatch(M, der, &der.object); runTestDispatch(M, dref2, &dref2.object.object); runTestPropCVDispatch(M, obj_ptr, &obj_ptr->object); runTestPropCVDispatch(M, der_ptr, &der_ptr->object); runTestNoPropDispatch(M, dref, &dref.object.object); } } template void runTestDispatch(Fn M, T& obj, ObjectType* expect) { runTest (M, C_(obj), expect); runTest (M, C_(obj), expect); runTest (M, C_(obj), expect); runTest(M, C_(obj), expect); } template void runTestPropCVDispatch(Fn M, T& obj, ObjectType* expect) { runTest (M, obj, expect); runTest (M, makeConst(obj), expect); runTest (M, makeVolatile(obj), expect); runTest(M, makeCV(obj), expect); } template void runTestNoPropDispatch(Fn M, T& obj, ObjectType* expect) { runTest(M, C_(obj), expect); runTest(M, C_(obj), expect); runTest(M, C_(obj), expect); runTest(M, C_(obj), expect); } template void runTest(Fn M, const T& obj, ObjectType* expect) { static_assert((std::is_same< decltype(std::__invoke(M, obj)), Expect >::value), ""); Expect e = std::__invoke(M, obj); assert(&e == expect); } template void runTest(Fn M, T& obj, ObjectType* expect ) { { static_assert((std::is_same< decltype(std::__invoke(M, std::forward(obj))), Expect >::value), ""); Expect e = std::__invoke(M, std::forward(obj)); assert(&e == expect); } } }; int main(int, char**) { TestCase::run(); TestCase::run(); TestCase::run(); TestCase::run(); TestCase::run(); return 0; }