brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.9 KiB · 3a8d141 Raw
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