//===----------------------------------------------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // 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 "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); #if TEST_STD_VER >= 11 runTestPropCVDispatch(M, rref, &(rref.get().object)); runTestPropCVDispatch(M, drref, &(drref.get().object)); #endif 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); #if TEST_STD_VER >= 11 runTestPropCVDispatch(M, rref, &(rref.get().object)); runTestPropCVDispatch(M, drref, &(drref.get().object)); #endif 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); #if TEST_STD_VER >= 11 runTestPropCVDispatch(M, rref, &(rref.get().object)); runTestPropCVDispatch(M, drref, &(drref.get().object)); #endif 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); #if TEST_STD_VER >= 11 runTestPropCVDispatch(M, rref, &(rref.get().object)); runTestPropCVDispatch(M, drref, &(drref.get().object)); #endif 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); #if TEST_STD_VER >= 11 runTest (M, C_(obj), expect); runTest (M, C_(obj), expect); runTest (M, C_(obj), expect); runTest(M, C_(obj), expect); #endif } 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); #if TEST_STD_VER >= 11 runTest(M, C_(obj), expect); runTest(M, C_(obj), expect); runTest(M, C_(obj), expect); runTest(M, C_(obj), expect); #endif } 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 #if TEST_STD_VER >= 11 void runTest(Fn M, T&& obj, ObjectType* expect) { #else void runTest(Fn M, T& obj, ObjectType* expect ) { #endif { 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); } #if TEST_STD_VER >= 11 { static_assert((std::is_same< decltype(std::__invoke_constexpr(M, std::forward(obj))), Expect >::value), ""); Expect e = std::__invoke_constexpr(M, std::forward(obj)); assert(&e == expect); } #endif } }; int main() { TestCase::run(); TestCase::run(); TestCase::run(); TestCase::run(); TestCase::run(); }