diff options
11 files changed, 409 insertions, 62 deletions
diff --git a/libcxx/include/__functional_base b/libcxx/include/__functional_base index 52c535aa3ea..3274842dc93 100644 --- a/libcxx/include/__functional_base +++ b/libcxx/include/__functional_base @@ -322,6 +322,17 @@ __invoke(_Fp&& __f, _A0&& __a0, _Args&& ...__args) return (_VSTD::forward<_A0>(__a0).*__f)(_VSTD::forward<_Args>(__args)...); } + +template <class _Fp, class _A0, class ..._Args, + class> +inline _LIBCPP_INLINE_VISIBILITY +auto +__invoke(_Fp&& __f, _A0&& __a0, _Args&& ...__args) + -> decltype((__a0.get().*__f)(_VSTD::forward<_Args>(__args)...)) +{ + return (__a0.get().*__f)(_VSTD::forward<_Args>(__args)...); +} + template <class _Fp, class _A0, class ..._Args, class> inline _LIBCPP_INLINE_VISIBILITY @@ -344,6 +355,17 @@ __invoke(_Fp&& __f, _A0&& __a0) return _VSTD::forward<_A0>(__a0).*__f; } + +template <class _Fp, class _A0, + class> +inline _LIBCPP_INLINE_VISIBILITY +auto +__invoke(_Fp&& __f, _A0&& __a0) + -> decltype(__a0.get().*__f) +{ + return __a0.get().*__f; +} + template <class _Fp, class _A0, class> inline _LIBCPP_INLINE_VISIBILITY @@ -577,10 +599,6 @@ public: #endif // _LIBCPP_HAS_NO_VARIADICS }; -template <class _Tp> struct __is_reference_wrapper_impl : public false_type {}; -template <class _Tp> struct __is_reference_wrapper_impl<reference_wrapper<_Tp> > : public true_type {}; -template <class _Tp> struct __is_reference_wrapper - : public __is_reference_wrapper_impl<typename remove_cv<_Tp>::type> {}; template <class _Tp> inline _LIBCPP_INLINE_VISIBILITY diff --git a/libcxx/include/type_traits b/libcxx/include/type_traits index b7b0d4d8b90..d4b857e91b2 100644 --- a/libcxx/include/type_traits +++ b/libcxx/include/type_traits @@ -369,6 +369,7 @@ namespace std _LIBCPP_BEGIN_NAMESPACE_STD template <class _T1, class _T2> struct _LIBCPP_TYPE_VIS_ONLY pair; +template <class _Tp> class _LIBCPP_TYPE_VIS_ONLY reference_wrapper; template <class> struct __void_t { typedef void type; }; @@ -3965,6 +3966,11 @@ template <class _Tp> _LIBCPP_CONSTEXPR bool is_trivial_v = is_trivial<_Tp>::value; #endif +template <class _Tp> struct __is_reference_wrapper_impl : public false_type {}; +template <class _Tp> struct __is_reference_wrapper_impl<reference_wrapper<_Tp> > : public true_type {}; +template <class _Tp> struct __is_reference_wrapper + : public __is_reference_wrapper_impl<typename remove_cv<_Tp>::type> {}; + #ifndef _LIBCPP_HAS_NO_VARIADICS // Check for complete types @@ -4111,6 +4117,15 @@ struct __check_complete<_Rp _Class::*> { }; + +template <class _Fp, class _A0> +using __arg_is_base_of_ptm = + is_base_of<typename remove_reference<typename __member_pointer_traits<typename remove_reference<_Fp>::type>::_ClassType>::type, + typename remove_reference<_A0>::type>; + +template <class _A0> +using __arg_is_reference_wrapper = __is_reference_wrapper<typename decay<_A0>::type>; + // __invoke forward declarations // fall back - none of the bullets @@ -4120,14 +4135,13 @@ auto __invoke(__any, _Args&& ...__args) -> __nat; -// bullets 1 and 2 +// bullets 1, 2 and 3 template <class _Fp, class _A0, class ..._Args, class = typename enable_if < is_member_function_pointer<typename remove_reference<_Fp>::type>::value && - is_base_of<typename remove_reference<typename __member_pointer_traits<typename remove_reference<_Fp>::type>::_ClassType>::type, - typename remove_reference<_A0>::type>::value + __arg_is_base_of_ptm<_Fp, _A0>::value >::type > _LIBCPP_INLINE_VISIBILITY @@ -4135,12 +4149,25 @@ auto __invoke(_Fp&& __f, _A0&& __a0, _Args&& ...__args) -> decltype((_VSTD::forward<_A0>(__a0).*__f)(_VSTD::forward<_Args>(__args)...)); + template <class _Fp, class _A0, class ..._Args, class = typename enable_if < is_member_function_pointer<typename remove_reference<_Fp>::type>::value && - !is_base_of<typename remove_reference<typename __member_pointer_traits<typename remove_reference<_Fp>::type>::_ClassType>::type, - typename remove_reference<_A0>::type>::value + __arg_is_reference_wrapper<_A0>::value + >::type + > +_LIBCPP_INLINE_VISIBILITY +auto +__invoke(_Fp&& __f, _A0&& __a0, _Args&& ...__args) + -> decltype((__a0.get().*__f)(_VSTD::forward<_Args>(__args)...)); + +template <class _Fp, class _A0, class ..._Args, + class = typename enable_if + < + is_member_function_pointer<typename remove_reference<_Fp>::type>::value && + !__arg_is_base_of_ptm<_Fp, _A0>::value && + !__arg_is_reference_wrapper<_A0>::value >::type > _LIBCPP_INLINE_VISIBILITY @@ -4148,14 +4175,13 @@ auto __invoke(_Fp&& __f, _A0&& __a0, _Args&& ...__args) -> decltype(((*_VSTD::forward<_A0>(__a0)).*__f)(_VSTD::forward<_Args>(__args)...)); -// bullets 3 and 4 +// bullets 4, 5 and 6 template <class _Fp, class _A0, class = typename enable_if < is_member_object_pointer<typename remove_reference<_Fp>::type>::value && - is_base_of<typename __member_pointer_traits<typename remove_reference<_Fp>::type>::_ClassType, - typename remove_reference<_A0>::type>::value + __arg_is_base_of_ptm<_Fp, _A0>::value >::type > _LIBCPP_INLINE_VISIBILITY @@ -4163,12 +4189,25 @@ auto __invoke(_Fp&& __f, _A0&& __a0) -> decltype(_VSTD::forward<_A0>(__a0).*__f); + +template <class _Fp, class _A0, + class = typename enable_if + < + is_member_object_pointer<typename remove_reference<_Fp>::type>::value && + __arg_is_reference_wrapper<_A0>::value + >::type + > +_LIBCPP_INLINE_VISIBILITY +auto +__invoke(_Fp&& __f, _A0&& __a0) + -> decltype(__a0.get().*__f); + template <class _Fp, class _A0, class = typename enable_if < is_member_object_pointer<typename remove_reference<_Fp>::type>::value && - !is_base_of<typename __member_pointer_traits<typename remove_reference<_Fp>::type>::_ClassType, - typename remove_reference<_A0>::type>::value + !__arg_is_base_of_ptm<_Fp, _A0>::value && + !__arg_is_reference_wrapper<_A0>::value >::type > _LIBCPP_INLINE_VISIBILITY @@ -4176,7 +4215,7 @@ auto __invoke(_Fp&& __f, _A0&& __a0) -> decltype((*_VSTD::forward<_A0>(__a0)).*__f); -// bullet 5 +// bullet 7 template <class _Fp, class ..._Args> _LIBCPP_INLINE_VISIBILITY diff --git a/libcxx/include/utility b/libcxx/include/utility index c9f5785b3d4..6db323e77fa 100644 --- a/libcxx/include/utility +++ b/libcxx/include/utility @@ -501,7 +501,6 @@ swap(pair<_T1, _T2>& __x, pair<_T1, _T2>& __y) #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES -template <class _Tp> class _LIBCPP_TYPE_VIS_ONLY reference_wrapper; template <class _Tp> struct __make_pair_return_impl diff --git a/libcxx/test/std/utilities/function.objects/func.invoke/invoke.pass.cpp b/libcxx/test/std/utilities/function.objects/func.invoke/invoke.pass.cpp index 97b0b4d158a..3f02c7c4c81 100644 --- a/libcxx/test/std/utilities/function.objects/func.invoke/invoke.pass.cpp +++ b/libcxx/test/std/utilities/function.objects/func.invoke/invoke.pass.cpp @@ -174,6 +174,32 @@ void bullet_one_two_tests() { } { TestClass cl_obj(42); + std::reference_wrapper<TestClass> cl(cl_obj); + test_b12<int&(NonCopyable&&) &, int&>(cl); + test_b12<int const&(NonCopyable&&) const &, int const&>(cl); + test_b12<int volatile&(NonCopyable&&) volatile &, int volatile&>(cl); + test_b12<int const volatile&(NonCopyable&&) const volatile &, int const volatile&>(cl); + + test_b12<int&(NonCopyable&&) &, int&>(std::move(cl)); + test_b12<int const&(NonCopyable&&) const &, int const&>(std::move(cl)); + test_b12<int volatile&(NonCopyable&&) volatile &, int volatile&>(std::move(cl)); + test_b12<int const volatile&(NonCopyable&&) const volatile &, int const volatile&>(std::move(cl)); + } + { + DerivedFromTestClass cl_obj(42); + std::reference_wrapper<DerivedFromTestClass> cl(cl_obj); + test_b12<int&(NonCopyable&&) &, int&>(cl); + test_b12<int const&(NonCopyable&&) const &, int const&>(cl); + test_b12<int volatile&(NonCopyable&&) volatile &, int volatile&>(cl); + test_b12<int const volatile&(NonCopyable&&) const volatile &, int const volatile&>(cl); + + test_b12<int&(NonCopyable&&) &, int&>(std::move(cl)); + test_b12<int const&(NonCopyable&&) const &, int const&>(std::move(cl)); + test_b12<int volatile&(NonCopyable&&) volatile &, int volatile&>(std::move(cl)); + test_b12<int const volatile&(NonCopyable&&) const volatile &, int const volatile&>(std::move(cl)); + } + { + TestClass cl_obj(42); TestClass *cl = &cl_obj; test_b12<int&(NonCopyable&&) &, int&>(cl); test_b12<int const&(NonCopyable&&) const &, int const&>(cl); @@ -219,6 +245,22 @@ void bullet_three_four_tests() { } { typedef TestClass Fn; + Fn cl(42); + test_b34<int&>(std::reference_wrapper<Fn>(cl)); + test_b34<int const&>(std::reference_wrapper<Fn const>(cl)); + test_b34<int volatile&>(std::reference_wrapper<Fn volatile>(cl)); + test_b34<int const volatile&>(std::reference_wrapper<Fn const volatile>(cl)); + } + { + typedef DerivedFromTestClass Fn; + Fn cl(42); + test_b34<int&>(std::reference_wrapper<Fn>(cl)); + test_b34<int const&>(std::reference_wrapper<Fn const>(cl)); + test_b34<int volatile&>(std::reference_wrapper<Fn volatile>(cl)); + test_b34<int const volatile&>(std::reference_wrapper<Fn const volatile>(cl)); + } + { + typedef TestClass Fn; Fn cl_obj(42); Fn* cl = &cl_obj; test_b34<int&>(cl); 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); }; diff --git a/libcxx/test/std/utilities/meta/meta.trans/meta.trans.other/result_of.pass.cpp b/libcxx/test/std/utilities/meta/meta.trans/meta.trans.other/result_of.pass.cpp index 5a925bb34b2..3ac7d1bc9df 100644 --- a/libcxx/test/std/utilities/meta/meta.trans/meta.trans.other/result_of.pass.cpp +++ b/libcxx/test/std/utilities/meta/meta.trans/meta.trans.other/result_of.pass.cpp @@ -13,6 +13,7 @@ #include <type_traits> #include <memory> +#include <cassert> #include "test_macros.h" struct S @@ -25,6 +26,11 @@ struct S double const volatile& operator()(char, int&) const volatile; }; + +struct SD : public S { }; + +struct NotDerived {}; + template <class Tp> struct Voider { typedef void type; @@ -52,6 +58,7 @@ void test_no_result() int main() { + typedef NotDerived ND; { // functor object test_result_of<S(int), short> (); test_result_of<S&(unsigned char, int&), double> (); @@ -90,32 +97,64 @@ int main() typedef int (S::*PMS0)(); typedef int* (S::*PMS1)(long); typedef int& (S::*PMS2)(long, int); - test_result_of<PMS0( S), int> (); - test_result_of<PMS0( S&), int> (); - test_result_of<PMS0( S*), int> (); - test_result_of<PMS0( S*&), int> (); - test_result_of<PMS0(std::unique_ptr<S>), int> (); + test_result_of<PMS0( S), int> (); + test_result_of<PMS0( S&), int> (); + test_result_of<PMS0( S*), int> (); + test_result_of<PMS0( S*&), int> (); + test_result_of<PMS0( std::reference_wrapper<S>), int> (); + test_result_of<PMS0(const std::reference_wrapper<S>&), int> (); + test_result_of<PMS0( std::reference_wrapper<SD>), int> (); + test_result_of<PMS0(const std::reference_wrapper<SD>&), int> (); + test_result_of<PMS0(std::unique_ptr<S>), int> (); + test_result_of<PMS0(std::unique_ptr<SD>), int> (); test_no_result<PMS0(const S&)>(); test_no_result<PMS0(volatile S&)>(); test_no_result<PMS0(const volatile S&)>(); + test_no_result<PMS0(ND & )>(); + test_no_result<PMS0(const ND& )>(); + test_no_result<PMS0(std::unique_ptr<S const> )>(); + test_no_result<PMS0(std::reference_wrapper<S const>)>(); + test_no_result<PMS0(std::reference_wrapper<ND> )>(); + test_no_result<PMS0(std::unique_ptr<ND> )>(); - test_result_of<PMS1( S, int), int*> (); - test_result_of<PMS1( S&, int), int*> (); - test_result_of<PMS1( S*, int), int*> (); - test_result_of<PMS1( S*&, int), int*> (); - test_result_of<PMS1(std::unique_ptr<S>, int), int*> (); + test_result_of<PMS1( S, int), int*> (); + test_result_of<PMS1( S&, int), int*> (); + test_result_of<PMS1( S*, int), int*> (); + test_result_of<PMS1( S*&, int), int*> (); + test_result_of<PMS1(std::unique_ptr<S>, int), int*> (); + test_result_of<PMS1(std::unique_ptr<SD>, int), int*> (); + test_result_of<PMS1(std::reference_wrapper<S>, int), int*> (); + test_result_of<PMS1(const std::reference_wrapper<S>&, int), int*> (); + test_result_of<PMS1(std::reference_wrapper<SD>, int), int*> (); + test_result_of<PMS1(const std::reference_wrapper<SD>&, int), int*> (); test_no_result<PMS1(const S&, int)>(); test_no_result<PMS1(volatile S&, int)>(); test_no_result<PMS1(const volatile S&, int)>(); + test_no_result<PMS1(ND &, int)>(); + test_no_result<PMS1(const ND&, int)>(); + test_no_result<PMS1(std::unique_ptr<S const>, int)>(); + test_no_result<PMS1(std::reference_wrapper<S const>, int)>(); + test_no_result<PMS1(std::reference_wrapper<ND>, int)>(); + test_no_result<PMS1(std::unique_ptr<ND>, int)>(); test_result_of<PMS2( S, int, int), int&> (); test_result_of<PMS2( S&, int, int), int&> (); test_result_of<PMS2( S*, int, int), int&> (); test_result_of<PMS2( S*&, int, int), int&> (); test_result_of<PMS2(std::unique_ptr<S>, int, int), int&> (); + test_result_of<PMS2(std::unique_ptr<SD>, int, int), int&> (); + test_result_of<PMS2(std::reference_wrapper<S>, int, int), int&> (); + test_result_of<PMS2(const std::reference_wrapper<S>&, int, int), int&> (); + test_result_of<PMS2(std::reference_wrapper<SD>, int, int), int&> (); + test_result_of<PMS2(const std::reference_wrapper<SD>&, int, int), int&> (); test_no_result<PMS2(const S&, int, int)>(); test_no_result<PMS2(volatile S&, int, int)>(); test_no_result<PMS2(const volatile S&, int, int)>(); + test_no_result<PMS2(std::unique_ptr<S const>, int, int)>(); + test_no_result<PMS2(std::reference_wrapper<S const>, int, int)>(); + test_no_result<PMS2(const ND&, int, int)>(); + test_no_result<PMS2(std::reference_wrapper<ND>, int, int)>(); + test_no_result<PMS2(std::unique_ptr<ND>, int, int)>(); typedef int (S::*PMS0C)() const; typedef int* (S::*PMS1C)(long) const; @@ -128,6 +167,15 @@ int main() test_result_of<PMS0C( S*&), int> (); test_result_of<PMS0C(const S*&), int> (); test_result_of<PMS0C(std::unique_ptr<S>), int> (); + test_result_of<PMS0C(std::unique_ptr<SD>), int> (); + test_result_of<PMS0C(std::reference_wrapper<S> ), int> (); + test_result_of<PMS0C(std::reference_wrapper<const S> ), int> (); + test_result_of<PMS0C(const std::reference_wrapper<S> & ), int> (); + test_result_of<PMS0C(const std::reference_wrapper<const S> &), int> (); + test_result_of<PMS0C(std::reference_wrapper<SD> ), int> (); + test_result_of<PMS0C(std::reference_wrapper<const SD> ), int> (); + test_result_of<PMS0C(const std::reference_wrapper<SD> & ), int> (); + test_result_of<PMS0C(const std::reference_wrapper<const SD> &), int> (); test_no_result<PMS0C(volatile S&)>(); test_no_result<PMS0C(const volatile S&)>(); @@ -248,5 +296,16 @@ int main() test_result_of<PMD(volatile S*), volatile char&> (); test_result_of<PMD(const volatile S&), const volatile char&> (); test_result_of<PMD(const volatile S*), const volatile char&> (); + test_result_of<PMD(SD&), char &>(); + test_result_of<PMD(SD const&), const char&>(); + test_result_of<PMD(SD*), char&>(); + test_result_of<PMD(const SD*), const char&>(); + test_result_of<PMD(std::unique_ptr<S>), char &>(); + test_result_of<PMD(std::unique_ptr<S const>), const char&>(); +#if TEST_STD_VER >= 11 + test_result_of<PMD(std::reference_wrapper<S>), char&>(); + test_result_of<PMD(std::reference_wrapper<S const>), const char&>(); +#endif + test_no_result<PMD(ND&)>(); } } diff --git a/libcxx/test/std/utilities/meta/meta.trans/meta.trans.other/result_of11.pass.cpp b/libcxx/test/std/utilities/meta/meta.trans/meta.trans.other/result_of11.pass.cpp index 6996cddc08b..a00887384d4 100644 --- a/libcxx/test/std/utilities/meta/meta.trans/meta.trans.other/result_of11.pass.cpp +++ b/libcxx/test/std/utilities/meta/meta.trans/meta.trans.other/result_of11.pass.cpp @@ -14,6 +14,8 @@ // result_of<Fn(ArgTypes...)> #include <type_traits> +#include <memory> +#include <utility> #include "test_macros.h" struct wat @@ -23,6 +25,8 @@ struct wat }; struct F {}; +struct FD : public F {}; +struct NotDerived {}; template <class T, class U> void test_result_of_imp() @@ -35,6 +39,7 @@ void test_result_of_imp() int main() { + typedef NotDerived ND; { typedef char F::*PMD; test_result_of_imp<PMD(F &), char &>(); @@ -51,6 +56,31 @@ int main() test_result_of_imp<PMD(F const ), char &&>(); test_result_of_imp<PMD(F volatile ), char &&>(); test_result_of_imp<PMD(F const volatile ), char &&>(); + + test_result_of_imp<PMD(FD &), char &>(); + test_result_of_imp<PMD(FD const &), char const &>(); + test_result_of_imp<PMD(FD volatile &), char volatile &>(); + test_result_of_imp<PMD(FD const volatile &), char const volatile &>(); + + test_result_of_imp<PMD(FD &&), char &&>(); + test_result_of_imp<PMD(FD const &&), char const &&>(); + test_result_of_imp<PMD(FD volatile &&), char volatile &&>(); + test_result_of_imp<PMD(FD const volatile &&), char const volatile &&>(); + + test_result_of_imp<PMD(FD ), char &&>(); + test_result_of_imp<PMD(FD const ), char &&>(); + test_result_of_imp<PMD(FD volatile ), char &&>(); + test_result_of_imp<PMD(FD const volatile ), char &&>(); + + test_result_of_imp<PMD(std::unique_ptr<F>), char &>(); + test_result_of_imp<PMD(std::unique_ptr<F const>), const char &>(); + test_result_of_imp<PMD(std::unique_ptr<FD>), char &>(); + test_result_of_imp<PMD(std::unique_ptr<FD const>), const char &>(); + + test_result_of_imp<PMD(std::reference_wrapper<F>), char &>(); + test_result_of_imp<PMD(std::reference_wrapper<F const>), const char &>(); + test_result_of_imp<PMD(std::reference_wrapper<FD>), char &>(); + test_result_of_imp<PMD(std::reference_wrapper<FD const>), const char &>(); } { test_result_of_imp<int (F::* (F &)) () &, int> (); @@ -83,6 +113,42 @@ int main() test_result_of_imp<int (F::* (F volatile )) () const volatile &&, int> (); test_result_of_imp<int (F::* (F const volatile )) () const volatile &&, int> (); } + { + test_result_of_imp<int (F::* (FD &)) () &, int> (); + test_result_of_imp<int (F::* (FD &)) () const &, int> (); + test_result_of_imp<int (F::* (FD &)) () volatile &, int> (); + test_result_of_imp<int (F::* (FD &)) () const volatile &, int> (); + test_result_of_imp<int (F::* (FD const &)) () const &, int> (); + test_result_of_imp<int (F::* (FD const &)) () const volatile &, int> (); + test_result_of_imp<int (F::* (FD volatile &)) () volatile &, int> (); + test_result_of_imp<int (F::* (FD volatile &)) () const volatile &, int> (); + test_result_of_imp<int (F::* (FD const volatile &)) () const volatile &, int> (); + + test_result_of_imp<int (F::* (FD &&)) () &&, int> (); + test_result_of_imp<int (F::* (FD &&)) () const &&, int> (); + test_result_of_imp<int (F::* (FD &&)) () volatile &&, int> (); + test_result_of_imp<int (F::* (FD &&)) () const volatile &&, int> (); + test_result_of_imp<int (F::* (FD const &&)) () const &&, int> (); + test_result_of_imp<int (F::* (FD const &&)) () const volatile &&, int> (); + test_result_of_imp<int (F::* (FD volatile &&)) () volatile &&, int> (); + test_result_of_imp<int (F::* (FD volatile &&)) () const volatile &&, int> (); + test_result_of_imp<int (F::* (FD const volatile &&)) () const volatile &&, int> (); + test_result_of_imp<int (F::* (FD )) () &&, int> (); + test_result_of_imp<int (F::* (FD )) () const &&, int> (); + test_result_of_imp<int (F::* (FD )) () volatile &&, int> (); + test_result_of_imp<int (F::* (FD )) () const volatile &&, int> (); + test_result_of_imp<int (F::* (FD const )) () const &&, int> (); + test_result_of_imp<int (F::* (FD const )) () const volatile &&, int> (); + test_result_of_imp<int (F::* (FD volatile )) () volatile &&, int> (); + test_result_of_imp<int (F::* (FD volatile )) () const volatile &&, int> (); + test_result_of_imp<int (F::* (FD const volatile )) () const volatile &&, int> (); + } + { + test_result_of_imp<int (F::* (std::reference_wrapper<F>)) (), int>(); + test_result_of_imp<int (F::* (std::reference_wrapper<const F>)) () const, int>(); + test_result_of_imp<int (F::* (std::unique_ptr<F> )) (), int>(); + test_result_of_imp<int (F::* (std::unique_ptr<const F> )) () const, int>(); + } test_result_of_imp<decltype(&wat::foo)(wat), void>(); } diff --git a/libcxx/www/cxx1z_status.html b/libcxx/www/cxx1z_status.html index 661e312c125..25d1350c95e 100644 --- a/libcxx/www/cxx1z_status.html +++ b/libcxx/www/cxx1z_status.html @@ -172,7 +172,7 @@ <tr><td><a href="http://cplusplus.github.io/LWG/lwg-defects.html#2133">2133</a></td><td>Attitude to overloaded comma for iterators</td><td>Kona</td><td>Complete</td></tr> <tr><td><a href="http://cplusplus.github.io/LWG/lwg-defects.html#2156">2156</a></td><td>Unordered containers' <tt>reserve(n)</tt> reserves for <tt>n-1</tt> elements</td><td>Kona</td><td>Complete</td></tr> <tr><td><a href="http://cplusplus.github.io/LWG/lwg-defects.html#2218">2218</a></td><td>Unclear how containers use <tt>allocator_traits::construct()</tt></td><td>Kona</td><td></td></tr> - <tr><td><a href="http://cplusplus.github.io/LWG/lwg-defects.html#2219">2219</a></td><td><tt><i>INVOKE</i></tt>-ing a pointer to member with a <tt>reference_wrapper</tt> as the object expression</td><td>Kona</td><td></td></tr> + <tr><td><a href="http://cplusplus.github.io/LWG/lwg-defects.html#2219">2219</a></td><td><tt><i>INVOKE</i></tt>-ing a pointer to member with a <tt>reference_wrapper</tt> as the object expression</td><td>Kona</td><td>Complete</td></tr> <tr><td><a href="http://cplusplus.github.io/LWG/lwg-defects.html#2224">2224</a></td><td>Ambiguous status of access to non-live objects</td><td>Kona</td><td>Complete</td></tr> <tr><td><a href="http://cplusplus.github.io/LWG/lwg-defects.html#2234">2234</a></td><td><tt>assert()</tt> should allow usage in constant expressions</td><td>Kona</td><td>Complete</td></tr> <tr><td><a href="http://cplusplus.github.io/LWG/lwg-defects.html#2244">2244</a></td><td>Issue on <tt>basic_istream::seekg</tt></td><td>Kona</td><td>Complete</td></tr> |