Implement LWG issue 2219 - support reference_wrapper in INVOKE

git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@266590 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Eric Fiselier
2016-04-18 06:17:30 +00:00
parent b952822a48
commit 134ff65b8f
11 changed files with 409 additions and 62 deletions

View File

@@ -322,6 +322,17 @@ __invoke(_Fp&& __f, _A0&& __a0, _Args&& ...__args)
return (_VSTD::forward<_A0>(__a0).*__f)(_VSTD::forward<_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, template <class _Fp, class _A0, class ..._Args,
class> class>
inline _LIBCPP_INLINE_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY
@@ -344,6 +355,17 @@ __invoke(_Fp&& __f, _A0&& __a0)
return _VSTD::forward<_A0>(__a0).*__f; 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, template <class _Fp, class _A0,
class> class>
inline _LIBCPP_INLINE_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY
@@ -577,10 +599,6 @@ public:
#endif // _LIBCPP_HAS_NO_VARIADICS #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> template <class _Tp>
inline _LIBCPP_INLINE_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY

View File

@@ -369,6 +369,7 @@ namespace std
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
template <class _T1, class _T2> struct _LIBCPP_TYPE_VIS_ONLY pair; template <class _T1, class _T2> struct _LIBCPP_TYPE_VIS_ONLY pair;
template <class _Tp> class _LIBCPP_TYPE_VIS_ONLY reference_wrapper;
template <class> template <class>
struct __void_t { typedef void type; }; struct __void_t { typedef void type; };
@@ -3965,6 +3966,11 @@ template <class _Tp> _LIBCPP_CONSTEXPR bool is_trivial_v
= is_trivial<_Tp>::value; = is_trivial<_Tp>::value;
#endif #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 #ifndef _LIBCPP_HAS_NO_VARIADICS
// Check for complete types // 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 // __invoke forward declarations
// fall back - none of the bullets // fall back - none of the bullets
@@ -4120,14 +4135,13 @@ auto
__invoke(__any, _Args&& ...__args) __invoke(__any, _Args&& ...__args)
-> __nat; -> __nat;
// bullets 1 and 2 // bullets 1, 2 and 3
template <class _Fp, class _A0, class ..._Args, template <class _Fp, class _A0, class ..._Args,
class = typename enable_if class = typename enable_if
< <
is_member_function_pointer<typename remove_reference<_Fp>::type>::value && 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, __arg_is_base_of_ptm<_Fp, _A0>::value
typename remove_reference<_A0>::type>::value
>::type >::type
> >
_LIBCPP_INLINE_VISIBILITY _LIBCPP_INLINE_VISIBILITY
@@ -4135,12 +4149,25 @@ auto
__invoke(_Fp&& __f, _A0&& __a0, _Args&& ...__args) __invoke(_Fp&& __f, _A0&& __a0, _Args&& ...__args)
-> decltype((_VSTD::forward<_A0>(__a0).*__f)(_VSTD::forward<_Args>(__args)...)); -> decltype((_VSTD::forward<_A0>(__a0).*__f)(_VSTD::forward<_Args>(__args)...));
template <class _Fp, class _A0, class ..._Args, template <class _Fp, class _A0, class ..._Args,
class = typename enable_if class = typename enable_if
< <
is_member_function_pointer<typename remove_reference<_Fp>::type>::value && 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, __arg_is_reference_wrapper<_A0>::value
typename remove_reference<_A0>::type>::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 >::type
> >
_LIBCPP_INLINE_VISIBILITY _LIBCPP_INLINE_VISIBILITY
@@ -4148,14 +4175,13 @@ auto
__invoke(_Fp&& __f, _A0&& __a0, _Args&& ...__args) __invoke(_Fp&& __f, _A0&& __a0, _Args&& ...__args)
-> decltype(((*_VSTD::forward<_A0>(__a0)).*__f)(_VSTD::forward<_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, template <class _Fp, class _A0,
class = typename enable_if class = typename enable_if
< <
is_member_object_pointer<typename remove_reference<_Fp>::type>::value && is_member_object_pointer<typename remove_reference<_Fp>::type>::value &&
is_base_of<typename __member_pointer_traits<typename remove_reference<_Fp>::type>::_ClassType, __arg_is_base_of_ptm<_Fp, _A0>::value
typename remove_reference<_A0>::type>::value
>::type >::type
> >
_LIBCPP_INLINE_VISIBILITY _LIBCPP_INLINE_VISIBILITY
@@ -4163,12 +4189,25 @@ auto
__invoke(_Fp&& __f, _A0&& __a0) __invoke(_Fp&& __f, _A0&& __a0)
-> decltype(_VSTD::forward<_A0>(__a0).*__f); -> decltype(_VSTD::forward<_A0>(__a0).*__f);
template <class _Fp, class _A0, template <class _Fp, class _A0,
class = typename enable_if class = typename enable_if
< <
is_member_object_pointer<typename remove_reference<_Fp>::type>::value && is_member_object_pointer<typename remove_reference<_Fp>::type>::value &&
!is_base_of<typename __member_pointer_traits<typename remove_reference<_Fp>::type>::_ClassType, __arg_is_reference_wrapper<_A0>::value
typename remove_reference<_A0>::type>::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 &&
!__arg_is_base_of_ptm<_Fp, _A0>::value &&
!__arg_is_reference_wrapper<_A0>::value
>::type >::type
> >
_LIBCPP_INLINE_VISIBILITY _LIBCPP_INLINE_VISIBILITY
@@ -4176,7 +4215,7 @@ auto
__invoke(_Fp&& __f, _A0&& __a0) __invoke(_Fp&& __f, _A0&& __a0)
-> decltype((*_VSTD::forward<_A0>(__a0)).*__f); -> decltype((*_VSTD::forward<_A0>(__a0)).*__f);
// bullet 5 // bullet 7
template <class _Fp, class ..._Args> template <class _Fp, class ..._Args>
_LIBCPP_INLINE_VISIBILITY _LIBCPP_INLINE_VISIBILITY

View File

@@ -501,7 +501,6 @@ swap(pair<_T1, _T2>& __x, pair<_T1, _T2>& __y)
#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
template <class _Tp> class _LIBCPP_TYPE_VIS_ONLY reference_wrapper;
template <class _Tp> template <class _Tp>
struct __make_pair_return_impl struct __make_pair_return_impl

View File

@@ -172,6 +172,32 @@ void bullet_one_two_tests() {
test_b12<int volatile&&(NonCopyable&&) volatile &&, int volatile&&>(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)); test_b12<int const volatile&&(NonCopyable&&) const volatile &&, int const volatile&&>(std::move(cl));
} }
{
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_obj(42);
TestClass *cl = &cl_obj; TestClass *cl = &cl_obj;
@@ -217,6 +243,22 @@ void bullet_three_four_tests() {
test_b34<int volatile&&>(static_cast<Fn volatile&&>(cl)); test_b34<int volatile&&>(static_cast<Fn volatile&&>(cl));
test_b34<int const volatile&&>(static_cast<Fn const volatile&&>(cl)); test_b34<int const volatile&&>(static_cast<Fn const volatile&&>(cl));
} }
{
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; typedef TestClass Fn;
Fn cl_obj(42); Fn cl_obj(42);

View File

@@ -14,12 +14,14 @@
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// TESTING INVOKE(f, t1, t2, ..., tN) // TESTING INVOKE(f, t1, t2, ..., tN)
// - Bullet 1 -- (t1.*f)(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: // 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 // 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: // Concerns:
// 1) cv-qualified member function signatures are accepted. // 1) cv-qualified member function signatures are accepted.
@@ -31,6 +33,7 @@
// as the call object. // as the call object.
// 7) Pointers 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 return types are properly deduced. // 8) Reference return types are properly deduced.
// 9) reference_wrappers are properly handled and unwrapped.
// //
// //
// Plan: // Plan:
@@ -123,6 +126,7 @@ private:
#endif // TEST_STD_VER >= 11 #endif // TEST_STD_VER >= 11
//============================================================================== //==============================================================================
// TestCase - A test case for a single member function. // TestCase - A test case for a single member function.
// ClassType - The type of the class being tested. // ClassType - The type of the class being tested.
@@ -151,6 +155,8 @@ private:
D* der_ptr = &der; D* der_ptr = &der;
DerefToType<T> dref; DerefToType<T> dref;
DerefPropType<T> dref2; DerefPropType<T> dref2;
std::reference_wrapper<T> rref(obj);
std::reference_wrapper<D> drref(der);
// (Plan-3) Dispatch based on the CV tags. // (Plan-3) Dispatch based on the CV tags.
CV tag; CV tag;
@@ -161,6 +167,10 @@ private:
runTestDispatchIf(NotRValue, tag, dref); runTestDispatchIf(NotRValue, tag, dref);
runTestDispatchIf(NotRValue, tag, obj_ptr); runTestDispatchIf(NotRValue, tag, obj_ptr);
runTestDispatchIf(NotRValue, tag, der_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> template <class QT, class Tp>
@@ -179,27 +189,43 @@ private:
template <class Tp> template <class Tp>
void runTestDispatch(Q_Const, Tp& v) { void runTestDispatch(Q_Const, Tp& v) {
Tp const& cv = v;
runTest(v); runTest(v);
runTest(cv); runTest(makeConst(v));
} }
template <class Tp> template <class Tp>
void runTestDispatch(Q_Volatile, Tp& v) { void runTestDispatch(Q_Volatile, Tp& v) {
Tp volatile& vv = v;
runTest(v); runTest(v);
runTest(vv); runTest(makeVolatile(v));
} }
template <class Tp> template <class Tp>
void runTestDispatch(Q_CV, Tp& v) { void runTestDispatch(Q_CV, Tp& v) {
Tp const& cv = v;
Tp volatile& vv = v;
Tp const volatile& cvv = v;
runTest(v); runTest(v);
runTest(cv); runTest(makeConst(v));
runTest(vv); runTest(makeVolatile(v));
runTest(cvv); 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> 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> {}; struct TestCase11 : public TestCaseImp<MemFun11, Sig, Arity, CV, RValue, true> {};
#endif #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() { int main() {
typedef void*& R; typedef void*& R;
typedef ArgType A; 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&&, ...) const &&, 3, Q_Const, /* RValue */ true>::run();
TestCase11<R(A&&, A&&, A&&, ...) volatile &&, 3, Q_Volatile, /* 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(); TestCase11<R(A&&, A&&, A&&, ...) const volatile &&, 3, Q_CV, /* RValue */ true>::run();
test_derived_from_ref_wrap();
#endif #endif
} }

View File

@@ -13,13 +13,15 @@
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// TESTING INVOKE(f, t1, t2, ..., tN) // 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: // Overview:
// Bullets 3 and 4 handle the case where 'f' is a pointer to member object. // Bullets 4, 5 and 6 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 // Bullet 4 only handles the cases where t1 is an object of type T or a
// type derived from 'T'. Bullet 4 handles all other cases. // type derived from 'T'. Bullet 5 handles cases where 't1' is a reference_wrapper
// and bullet 6 handles all other cases.
// //
// Concerns: // Concerns:
// 1) The return type is always an lvalue reference. // 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 // 6) All types that dereference to T or a type derived from T can be used
// as the call object. // as the call object.
// 7) Pointers 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 <functional>
#include <type_traits> #include <type_traits>
@@ -66,6 +69,8 @@ private:
Derived* der_ptr = &der; Derived* der_ptr = &der;
DerefToType<TestType> dref; DerefToType<TestType> dref;
DerefPropType<TestType> dref2; DerefPropType<TestType> dref2;
std::reference_wrapper<TestType> rref(obj);
std::reference_wrapper<Derived> drref(der);
{ {
typedef ObjectType (TestType::*MemPtr); typedef ObjectType (TestType::*MemPtr);
@@ -74,9 +79,13 @@ private:
runTestDispatch<E>(M, obj, &obj.object); runTestDispatch<E>(M, obj, &obj.object);
runTestDispatch<E>(M, der, &der.object); runTestDispatch<E>(M, der, &der.object);
runTestDispatch<E>(M, dref2, &dref2.object.object); runTestDispatch<E>(M, dref2, &dref2.object.object);
runTestPointerDispatch<E>(M, obj_ptr, &obj_ptr->object); runTestPropCVDispatch<E>(M, obj_ptr, &obj_ptr->object);
runTestPointerDispatch<E>(M, der_ptr, &der_ptr->object); runTestPropCVDispatch<E>(M, der_ptr, &der_ptr->object);
runTestPointerDispatch<E>(M, dref, &dref.object.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); typedef ObjectType const (TestType::*CMemPtr);
@@ -85,9 +94,13 @@ private:
runTestDispatch<E>(M, obj, &obj.object); runTestDispatch<E>(M, obj, &obj.object);
runTestDispatch<E>(M, der, &der.object); runTestDispatch<E>(M, der, &der.object);
runTestDispatch<E>(M, dref2, &dref2.object.object); runTestDispatch<E>(M, dref2, &dref2.object.object);
runTestPointerDispatch<E>(M, obj_ptr, &obj_ptr->object); runTestPropCVDispatch<E>(M, obj_ptr, &obj_ptr->object);
runTestPointerDispatch<E>(M, der_ptr, &der_ptr->object); runTestPropCVDispatch<E>(M, der_ptr, &der_ptr->object);
runTestPointerDispatch<E>(M, dref, &dref.object.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); typedef ObjectType volatile (TestType::*VMemPtr);
@@ -96,9 +109,13 @@ private:
runTestDispatch<E>(M, obj, &obj.object); runTestDispatch<E>(M, obj, &obj.object);
runTestDispatch<E>(M, der, &der.object); runTestDispatch<E>(M, der, &der.object);
runTestDispatch<E>(M, dref2, &dref2.object.object); runTestDispatch<E>(M, dref2, &dref2.object.object);
runTestPointerDispatch<E>(M, obj_ptr, &obj_ptr->object); runTestPropCVDispatch<E>(M, obj_ptr, &obj_ptr->object);
runTestPointerDispatch<E>(M, der_ptr, &der_ptr->object); runTestPropCVDispatch<E>(M, der_ptr, &der_ptr->object);
runTestPointerDispatch<E>(M, dref, &dref.object.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); typedef ObjectType const volatile (TestType::*CVMemPtr);
@@ -107,9 +124,13 @@ private:
runTestDispatch<E>(M, obj, &obj.object); runTestDispatch<E>(M, obj, &obj.object);
runTestDispatch<E>(M, der, &der.object); runTestDispatch<E>(M, der, &der.object);
runTestDispatch<E>(M, dref2, &dref2.object.object); runTestDispatch<E>(M, dref2, &dref2.object.object);
runTestPointerDispatch<E>(M, obj_ptr, &obj_ptr->object); runTestPropCVDispatch<E>(M, obj_ptr, &obj_ptr->object);
runTestPointerDispatch<E>(M, der_ptr, &der_ptr->object); runTestPropCVDispatch<E>(M, der_ptr, &der_ptr->object);
runTestPointerDispatch<E>(M, dref, &dref.object.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> 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 &>(obj), expect);
runTest<Expect&>(M, C_<T const&>(obj), expect); runTest<Expect&>(M, C_<T const&>(obj), expect);
runTest<Expect&>(M, C_<T volatile&>(obj), expect); runTest<Expect&>(M, C_<T volatile&>(obj), expect);
@@ -141,6 +170,15 @@ private:
#endif #endif
} }
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> template <class Expect, class Fn, class T>
#if TEST_STD_VER >= 11 #if TEST_STD_VER >= 11
void runTest(Fn M, T&& obj, ObjectType* expect) { void runTest(Fn M, T&& obj, ObjectType* expect) {
@@ -155,6 +193,9 @@ private:
} }
}; };
int main() { int main() {
TestCase<ArgType>::run(); TestCase<ArgType>::run();
TestCase<ArgType const>::run(); TestCase<ArgType const>::run();

View File

@@ -13,10 +13,10 @@
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// TESTING INVOKE(f, t1, t2, ..., tN) // TESTING INVOKE(f, t1, t2, ..., tN)
// - Bullet 5 -- f(t2, ..., tN) // - Bullet 7 -- f(t2, ..., tN)
// //
// Overview: // 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. // function.
// //
// Concerns: // Concerns:

View File

@@ -79,6 +79,40 @@ typedef Caster<Q_Const, true> MoveConstCaster;
typedef Caster<Q_Volatile, true> MoveVolatileCaster; typedef Caster<Q_Volatile, true> MoveVolatileCaster;
typedef Caster<Q_CV, true> MoveCVCaster; 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' // A shorter name for 'static_cast'
template <class QualType, class Tp> template <class QualType, class Tp>
QualType C_(Tp& v) { return static_cast<QualType>(v); }; QualType C_(Tp& v) { return static_cast<QualType>(v); };

View File

@@ -13,6 +13,7 @@
#include <type_traits> #include <type_traits>
#include <memory> #include <memory>
#include <cassert>
#include "test_macros.h" #include "test_macros.h"
struct S struct S
@@ -25,6 +26,11 @@ struct S
double const volatile& operator()(char, int&) const volatile; double const volatile& operator()(char, int&) const volatile;
}; };
struct SD : public S { };
struct NotDerived {};
template <class Tp> template <class Tp>
struct Voider { struct Voider {
typedef void type; typedef void type;
@@ -52,6 +58,7 @@ void test_no_result()
int main() int main()
{ {
typedef NotDerived ND;
{ // functor object { // functor object
test_result_of<S(int), short> (); test_result_of<S(int), short> ();
test_result_of<S&(unsigned char, int&), double> (); test_result_of<S&(unsigned char, int&), double> ();
@@ -94,28 +101,60 @@ int main()
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( 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<S>), int> ();
test_result_of<PMS0(std::unique_ptr<SD>), int> ();
test_no_result<PMS0(const S&)>(); test_no_result<PMS0(const S&)>();
test_no_result<PMS0(volatile S&)>(); test_no_result<PMS0(volatile S&)>();
test_no_result<PMS0(const 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( 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<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(const S&, int)>();
test_no_result<PMS1(volatile S&, int)>(); test_no_result<PMS1(volatile S&, int)>();
test_no_result<PMS1(const 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( 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<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(const S&, int, int)>();
test_no_result<PMS2(volatile S&, int, int)>(); test_no_result<PMS2(volatile S&, int, int)>();
test_no_result<PMS2(const 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::*PMS0C)() const;
typedef int* (S::*PMS1C)(long) const; typedef int* (S::*PMS1C)(long) const;
@@ -128,6 +167,15 @@ int main()
test_result_of<PMS0C( S*&), int> (); test_result_of<PMS0C( S*&), int> ();
test_result_of<PMS0C(const 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<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(volatile S&)>();
test_no_result<PMS0C(const 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(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(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&)>();
} }
} }

View File

@@ -14,6 +14,8 @@
// result_of<Fn(ArgTypes...)> // result_of<Fn(ArgTypes...)>
#include <type_traits> #include <type_traits>
#include <memory>
#include <utility>
#include "test_macros.h" #include "test_macros.h"
struct wat struct wat
@@ -23,6 +25,8 @@ struct wat
}; };
struct F {}; struct F {};
struct FD : public F {};
struct NotDerived {};
template <class T, class U> template <class T, class U>
void test_result_of_imp() void test_result_of_imp()
@@ -35,6 +39,7 @@ void test_result_of_imp()
int main() int main()
{ {
typedef NotDerived ND;
{ {
typedef char F::*PMD; typedef char F::*PMD;
test_result_of_imp<PMD(F &), char &>(); 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 const ), char &&>();
test_result_of_imp<PMD(F volatile ), char &&>(); test_result_of_imp<PMD(F volatile ), char &&>();
test_result_of_imp<PMD(F const 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> (); 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 volatile )) () const volatile &&, int> ();
test_result_of_imp<int (F::* (F const 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>(); test_result_of_imp<decltype(&wat::foo)(wat), void>();
} }

View File

@@ -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#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#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#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#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#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> <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>