//===----------------------------------------------------------------------===// // // 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 3 -- t1.*f // - Bullet 4 -- (*t1).*f // // Overview: // Bullets 3 and 4 handle the case where 'f' is a pointer to member object. // Bullet 3 only handles the cases where t1 is an object of type T or a // type derived from 'T'. Bullet 4 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. #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; { 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); runTestPointerDispatch(M, obj_ptr, &obj_ptr->object); runTestPointerDispatch(M, der_ptr, &der_ptr->object); runTestPointerDispatch(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); runTestPointerDispatch(M, obj_ptr, &obj_ptr->object); runTestPointerDispatch(M, der_ptr, &der_ptr->object); runTestPointerDispatch(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); runTestPointerDispatch(M, obj_ptr, &obj_ptr->object); runTestPointerDispatch(M, der_ptr, &der_ptr->object); runTestPointerDispatch(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); runTestPointerDispatch(M, obj_ptr, &obj_ptr->object); runTestPointerDispatch(M, der_ptr, &der_ptr->object); runTestPointerDispatch(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 runTestPointerDispatch(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 #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); } }; int main() { TestCase::run(); TestCase::run(); TestCase::run(); TestCase::run(); TestCase::run(); }