diff options
author | Eric Fiselier <eric@efcs.ca> | 2016-04-18 06:17:30 +0000 |
---|---|---|
committer | Eric Fiselier <eric@efcs.ca> | 2016-04-18 06:17:30 +0000 |
commit | 2152fd7682e3725449fc6483141dc55fc80dad16 (patch) | |
tree | ffc09c3c81b33127dc7ea73eccf76d9b8272de4a /libcxx/test/std/utilities/function.objects/func.require | |
parent | 76a7ca0f67379705773c4d1da89e546667ff25f2 (diff) | |
download | bcm5719-llvm-2152fd7682e3725449fc6483141dc55fc80dad16.tar.gz bcm5719-llvm-2152fd7682e3725449fc6483141dc55fc80dad16.zip |
Implement LWG issue 2219 - support reference_wrapper in INVOKE
llvm-svn: 266590
Diffstat (limited to 'libcxx/test/std/utilities/function.objects/func.require')
-rw-r--r-- | libcxx/test/std/utilities/function.objects/func.require/bullet_1_2_3.pass.cpp (renamed from libcxx/test/std/utilities/function.objects/func.require/bullet_1_and_2.pass.cpp) | 79 | ||||
-rw-r--r-- | libcxx/test/std/utilities/function.objects/func.require/bullet_4_5_6.pass.cpp (renamed from libcxx/test/std/utilities/function.objects/func.require/bullet_3_and_4.pass.cpp) | 77 | ||||
-rw-r--r-- | libcxx/test/std/utilities/function.objects/func.require/bullet_7.pass.cpp (renamed from libcxx/test/std/utilities/function.objects/func.require/bullet_5.pass.cpp) | 4 | ||||
-rw-r--r-- | libcxx/test/std/utilities/function.objects/func.require/invoke_helpers.h | 34 |
4 files changed, 159 insertions, 35 deletions
diff --git a/libcxx/test/std/utilities/function.objects/func.require/bullet_1_and_2.pass.cpp b/libcxx/test/std/utilities/function.objects/func.require/bullet_1_2_3.pass.cpp index e579f207a33..09e8e21137a 100644 --- a/libcxx/test/std/utilities/function.objects/func.require/bullet_1_and_2.pass.cpp +++ b/libcxx/test/std/utilities/function.objects/func.require/bullet_1_2_3.pass.cpp @@ -14,12 +14,14 @@ //------------------------------------------------------------------------------ // TESTING INVOKE(f, t1, t2, ..., tN) // - Bullet 1 -- (t1.*f)(t2, ..., tN) -// - Bullet 2 -- ((*t1).*f)(t2, ..., tN) +// - Bullet 2 -- (t1.get().*f)(t2, ..., tN) // t1 is a reference_wrapper +// - Bullet 3 -- ((*t1).*f)(t2, ..., tN) // // Overview: -// Bullets 1 and 2 handle the case where 'f' is a pointer to member function. +// Bullets 1, 2 and 3 handle the case where 'f' is a pointer to member function. // Bullet 1 only handles the cases where t1 is an object of type T or a -// type derived from 'T'. Bullet 2 handles all other cases. +// type derived from 'T'. Bullet 2 handles the case where 't1' is a reference +// wrapper and bullet 3 handles all other cases. // // Concerns: // 1) cv-qualified member function signatures are accepted. @@ -31,6 +33,7 @@ // as the call object. // 7) Pointers to T or a type derived from T can be used as the call object. // 8) Reference return types are properly deduced. +// 9) reference_wrappers are properly handled and unwrapped. // // // Plan: @@ -123,6 +126,7 @@ private: #endif // TEST_STD_VER >= 11 + //============================================================================== // TestCase - A test case for a single member function. // ClassType - The type of the class being tested. @@ -151,6 +155,8 @@ private: D* der_ptr = &der; DerefToType<T> dref; DerefPropType<T> dref2; + std::reference_wrapper<T> rref(obj); + std::reference_wrapper<D> drref(der); // (Plan-3) Dispatch based on the CV tags. CV tag; @@ -158,9 +164,13 @@ private: runTestDispatch(tag, obj); runTestDispatch(tag, der); runTestDispatch(tag, dref2); - runTestDispatchIf(NotRValue, tag, dref); - runTestDispatchIf(NotRValue, tag, obj_ptr); + runTestDispatchIf(NotRValue, tag, dref); + runTestDispatchIf(NotRValue, tag, obj_ptr); runTestDispatchIf(NotRValue, tag, der_ptr); +#if TEST_STD_VER >= 11 + runTestDispatchIf(NotRValue, tag, rref); + runTestDispatchIf(NotRValue, tag, drref); +#endif } template <class QT, class Tp> @@ -179,27 +189,43 @@ private: template <class Tp> void runTestDispatch(Q_Const, Tp& v) { - Tp const& cv = v; runTest(v); - runTest(cv); + runTest(makeConst(v)); } template <class Tp> void runTestDispatch(Q_Volatile, Tp& v) { - Tp volatile& vv = v; runTest(v); - runTest(vv); + runTest(makeVolatile(v)); + } template <class Tp> void runTestDispatch(Q_CV, Tp& v) { - Tp const& cv = v; - Tp volatile& vv = v; - Tp const volatile& cvv = v; runTest(v); - runTest(cv); - runTest(vv); - runTest(cvv); + runTest(makeConst(v)); + runTest(makeVolatile(v)); + runTest(makeCV(v)); + } + + template <class T> + void runTest(const std::reference_wrapper<T>& obj) { + typedef Caster<Q_None, RValue> SCast; + typedef Caster<Q_None, ArgRValue> ACast; + typedef CallSig (ClassType::*MemPtr); + // Delegate test to logic in invoke_helpers.h + BasicTest<MethodID<MemPtr>, Arity, SCast, ACast> b; + b.runTest( (MemPtr)&ClassType::f, obj); + } + + template <class T> + void runTest(T* obj) { + typedef Caster<Q_None, RValue> SCast; + typedef Caster<Q_None, ArgRValue> ACast; + typedef CallSig (ClassType::*MemPtr); + // Delegate test to logic in invoke_helpers.h + BasicTest<MethodID<MemPtr>, Arity, SCast, ACast> b; + b.runTest( (MemPtr)&ClassType::f, obj); } template <class Obj> @@ -221,6 +247,27 @@ template <class Sig, int Arity, class CV, bool RValue = false> struct TestCase11 : public TestCaseImp<MemFun11, Sig, Arity, CV, RValue, true> {}; #endif +template <class Tp> +struct DerivedFromRefWrap : public std::reference_wrapper<Tp> { + DerivedFromRefWrap(Tp& tp) : std::reference_wrapper<Tp>(tp) {} +}; + +#if TEST_STD_VER >= 11 +void test_derived_from_ref_wrap() { + int x = 42; + std::reference_wrapper<int> r(x); + std::reference_wrapper<std::reference_wrapper<int>> r2(r); + DerivedFromRefWrap<int> d(x); + auto get_fn = &std::reference_wrapper<int>::get; + auto& ret = std::__invoke(get_fn, r); + assert(&ret == &x); + auto& ret2 = std::__invoke(get_fn, d); + assert(&ret2 == &x); + auto& ret3 = std::__invoke(get_fn, r2); + assert(&ret3 == &x); +} +#endif + int main() { typedef void*& R; typedef ArgType A; @@ -314,5 +361,7 @@ int main() { TestCase11<R(A&&, A&&, A&&, ...) const &&, 3, Q_Const, /* RValue */ true>::run(); TestCase11<R(A&&, A&&, A&&, ...) volatile &&, 3, Q_Volatile, /* RValue */ true>::run(); TestCase11<R(A&&, A&&, A&&, ...) const volatile &&, 3, Q_CV, /* RValue */ true>::run(); + + test_derived_from_ref_wrap(); #endif }
\ No newline at end of file diff --git a/libcxx/test/std/utilities/function.objects/func.require/bullet_3_and_4.pass.cpp b/libcxx/test/std/utilities/function.objects/func.require/bullet_4_5_6.pass.cpp index b6fe190bd2a..2007c417a62 100644 --- a/libcxx/test/std/utilities/function.objects/func.require/bullet_3_and_4.pass.cpp +++ b/libcxx/test/std/utilities/function.objects/func.require/bullet_4_5_6.pass.cpp @@ -13,13 +13,15 @@ //------------------------------------------------------------------------------ // TESTING INVOKE(f, t1, t2, ..., tN) -// - Bullet 3 -- t1.*f -// - Bullet 4 -- (*t1).*f +// - Bullet 4 -- t1.*f +// - Bullet 5 -- t1.get().*f // t1 is a reference wrapper. +// - Bullet 6 -- (*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. +// 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. @@ -30,6 +32,7 @@ // 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 <functional> #include <type_traits> @@ -66,6 +69,8 @@ private: Derived* der_ptr = &der; DerefToType<TestType> dref; DerefPropType<TestType> dref2; + std::reference_wrapper<TestType> rref(obj); + std::reference_wrapper<Derived> drref(der); { typedef ObjectType (TestType::*MemPtr); @@ -74,9 +79,13 @@ private: runTestDispatch<E>(M, obj, &obj.object); runTestDispatch<E>(M, der, &der.object); runTestDispatch<E>(M, dref2, &dref2.object.object); - runTestPointerDispatch<E>(M, obj_ptr, &obj_ptr->object); - runTestPointerDispatch<E>(M, der_ptr, &der_ptr->object); - runTestPointerDispatch<E>(M, dref, &dref.object.object); + runTestPropCVDispatch<E>(M, obj_ptr, &obj_ptr->object); + runTestPropCVDispatch<E>(M, der_ptr, &der_ptr->object); +#if TEST_STD_VER >= 11 + runTestPropCVDispatch<E>(M, rref, &(rref.get().object)); + runTestPropCVDispatch<E>(M, drref, &(drref.get().object)); +#endif + runTestNoPropDispatch<E>(M, dref, &dref.object.object); } { typedef ObjectType const (TestType::*CMemPtr); @@ -85,9 +94,13 @@ private: runTestDispatch<E>(M, obj, &obj.object); runTestDispatch<E>(M, der, &der.object); runTestDispatch<E>(M, dref2, &dref2.object.object); - runTestPointerDispatch<E>(M, obj_ptr, &obj_ptr->object); - runTestPointerDispatch<E>(M, der_ptr, &der_ptr->object); - runTestPointerDispatch<E>(M, dref, &dref.object.object); + runTestPropCVDispatch<E>(M, obj_ptr, &obj_ptr->object); + runTestPropCVDispatch<E>(M, der_ptr, &der_ptr->object); +#if TEST_STD_VER >= 11 + runTestPropCVDispatch<E>(M, rref, &(rref.get().object)); + runTestPropCVDispatch<E>(M, drref, &(drref.get().object)); +#endif + runTestNoPropDispatch<E>(M, dref, &dref.object.object); } { typedef ObjectType volatile (TestType::*VMemPtr); @@ -96,9 +109,13 @@ private: runTestDispatch<E>(M, obj, &obj.object); runTestDispatch<E>(M, der, &der.object); runTestDispatch<E>(M, dref2, &dref2.object.object); - runTestPointerDispatch<E>(M, obj_ptr, &obj_ptr->object); - runTestPointerDispatch<E>(M, der_ptr, &der_ptr->object); - runTestPointerDispatch<E>(M, dref, &dref.object.object); + runTestPropCVDispatch<E>(M, obj_ptr, &obj_ptr->object); + runTestPropCVDispatch<E>(M, der_ptr, &der_ptr->object); +#if TEST_STD_VER >= 11 + runTestPropCVDispatch<E>(M, rref, &(rref.get().object)); + runTestPropCVDispatch<E>(M, drref, &(drref.get().object)); +#endif + runTestNoPropDispatch<E>(M, dref, &dref.object.object); } { typedef ObjectType const volatile (TestType::*CVMemPtr); @@ -107,9 +124,13 @@ private: runTestDispatch<E>(M, obj, &obj.object); runTestDispatch<E>(M, der, &der.object); runTestDispatch<E>(M, dref2, &dref2.object.object); - runTestPointerDispatch<E>(M, obj_ptr, &obj_ptr->object); - runTestPointerDispatch<E>(M, der_ptr, &der_ptr->object); - runTestPointerDispatch<E>(M, dref, &dref.object.object); + runTestPropCVDispatch<E>(M, obj_ptr, &obj_ptr->object); + runTestPropCVDispatch<E>(M, der_ptr, &der_ptr->object); +#if TEST_STD_VER >= 11 + runTestPropCVDispatch<E>(M, rref, &(rref.get().object)); + runTestPropCVDispatch<E>(M, drref, &(drref.get().object)); +#endif + runTestNoPropDispatch<E>(M, dref, &dref.object.object); } } @@ -128,7 +149,15 @@ private: } template <class Expect, class Fn, class T> - void runTestPointerDispatch(Fn M, T& obj, ObjectType* expect) { + void runTestPropCVDispatch(Fn M, T& obj, ObjectType* expect) { + runTest<Expect &> (M, obj, expect); + runTest<Expect const&> (M, makeConst(obj), expect); + runTest<Expect volatile&> (M, makeVolatile(obj), expect); + runTest<Expect const volatile&>(M, makeCV(obj), expect); + } + + template <class Expect, class Fn, class T> + void runTestNoPropDispatch(Fn M, T& obj, ObjectType* expect) { runTest<Expect&>(M, C_<T &>(obj), expect); runTest<Expect&>(M, C_<T const&>(obj), expect); runTest<Expect&>(M, C_<T volatile&>(obj), expect); @@ -142,6 +171,15 @@ private: } template <class Expect, class Fn, class T> + 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 <class Expect, class Fn, class T> #if TEST_STD_VER >= 11 void runTest(Fn M, T&& obj, ObjectType* expect) { #else @@ -155,6 +193,9 @@ private: } }; + + + int main() { TestCase<ArgType>::run(); TestCase<ArgType const>::run(); diff --git a/libcxx/test/std/utilities/function.objects/func.require/bullet_5.pass.cpp b/libcxx/test/std/utilities/function.objects/func.require/bullet_7.pass.cpp index 3f3c96a9b9b..0d14a350c89 100644 --- a/libcxx/test/std/utilities/function.objects/func.require/bullet_5.pass.cpp +++ b/libcxx/test/std/utilities/function.objects/func.require/bullet_7.pass.cpp @@ -13,10 +13,10 @@ //------------------------------------------------------------------------------ // TESTING INVOKE(f, t1, t2, ..., tN) -// - Bullet 5 -- f(t2, ..., tN) +// - Bullet 7 -- f(t2, ..., tN) // // Overview: -// Bullet 5 handles the cases where the first argument is not a member +// Bullet 7 handles the cases where the first argument is not a member // function. // // Concerns: diff --git a/libcxx/test/std/utilities/function.objects/func.require/invoke_helpers.h b/libcxx/test/std/utilities/function.objects/func.require/invoke_helpers.h index a85b39f3717..495703d0e32 100644 --- a/libcxx/test/std/utilities/function.objects/func.require/invoke_helpers.h +++ b/libcxx/test/std/utilities/function.objects/func.require/invoke_helpers.h @@ -79,6 +79,40 @@ typedef Caster<Q_Const, true> MoveConstCaster; typedef Caster<Q_Volatile, true> MoveVolatileCaster; typedef Caster<Q_CV, true> MoveCVCaster; + +template <class Tp> +Tp const& makeConst(Tp& ref) { return ref; } + +template <class Tp> +Tp const* makeConst(Tp* ptr) { return ptr; } + +template <class Tp> +std::reference_wrapper<const Tp> makeConst(std::reference_wrapper<Tp>& ref) { + return std::reference_wrapper<const Tp>(ref.get()); +} + +template <class Tp> +Tp volatile& makeVolatile(Tp& ref) { return ref; } + +template <class Tp> +Tp volatile* makeVolatile(Tp* ptr) { return ptr; } + +template <class Tp> +std::reference_wrapper<volatile Tp> makeVolatile(std::reference_wrapper<Tp>& ref) { + return std::reference_wrapper<volatile Tp>(ref.get()); +} + +template <class Tp> +Tp const volatile& makeCV(Tp& ref) { return ref; } + +template <class Tp> +Tp const volatile* makeCV(Tp* ptr) { return ptr; } + +template <class Tp> +std::reference_wrapper<const volatile Tp> makeCV(std::reference_wrapper<Tp>& ref) { + return std::reference_wrapper<const volatile Tp>(ref.get()); +} + // A shorter name for 'static_cast' template <class QualType, class Tp> QualType C_(Tp& v) { return static_cast<QualType>(v); }; |