Cleanup C++03 __invoke for Bullets 3 and 4.

The key changes in this patch are:

1. Remove the zero-argument overload in mem_fn. A member function must always
   be invoked with at least one argument, the class instance. The zero-argument
   operator()() in mem_fn would cause mem_fn to fail to compile when because
   the call to '__invoke(pm)' is not well formed.

2. Prevent evaluation of '__apply_cv<Tp, Ret>' when 'Ret' is a function type.
   'Ret' is a function type whenever 'Ret Tp::*' is a pointer to member function.
   Attempting to add cv and ref qualifiers to a function type can cause a hard
   compile error.

3. Remove the dummy overload __invoke(Rp Tp::*). It was present to help work
   around #1. It will be replaced with a different '__invoke' overload that
   represents a bad call to invoke.

After applying this patch the test func.wrap.func.inv/invoke.pass.cpp now
passes.

llvm-svn: 243370
This commit is contained in:
Eric Fiselier 2015-07-28 02:15:53 +00:00
parent d29116331d
commit e62bda70aa
2 changed files with 9 additions and 19 deletions

View File

@ -408,20 +408,15 @@ template <class _Rp, class _Tp, class _T1>
inline _LIBCPP_INLINE_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY
typename enable_if typename enable_if
< <
is_member_object_pointer<_Rp _Tp::*>::value &&
is_base_of<_Tp, typename remove_reference<_T1>::type>::value, is_base_of<_Tp, typename remove_reference<_T1>::type>::value,
typename __apply_cv<_T1, _Rp>::type& __apply_cv<_T1, _Rp>
>::type >::type::type&
__invoke(_Rp _Tp::* __f, _T1& __t1) __invoke(_Rp _Tp::* __f, _T1& __t1)
{ {
return __t1.*__f; return __t1.*__f;
} }
template <class _Rp, class _Tp>
inline _LIBCPP_INLINE_VISIBILITY
void
__invoke(_Rp _Tp::*)
{
}
// forth bullet // forth bullet
@ -439,10 +434,9 @@ struct __4th_helper<_T1, _Rp, true>
template <class _Rp, class _Tp, class _T1> template <class _Rp, class _Tp, class _T1>
inline _LIBCPP_INLINE_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY
typename __4th_helper<_T1, _Rp, typename __4th_helper<_T1, _Rp,
!is_base_of<_Tp, is_member_object_pointer<_Rp _Tp::*>::value &&
typename remove_reference<_T1>::type !is_base_of<_Tp, typename remove_reference<_T1>::type>::value
>::value >::type&
>::type&
__invoke(_Rp _Tp::* __f, _T1& __t1) __invoke(_Rp _Tp::* __f, _T1& __t1)
{ {
return (*__t1).*__f; return (*__t1).*__f;
@ -494,20 +488,20 @@ struct __invoke_return<_Fp, false>
typedef decltype(__invoke(_VSTD::declval<_Fp&>())) type; typedef decltype(__invoke(_VSTD::declval<_Fp&>())) type;
}; };
template <class _Tp, class _A0> template <class _Tp, class _A0, bool = is_member_object_pointer<_Tp>::value>
struct __invoke_return0 struct __invoke_return0
{ {
typedef decltype(__invoke(_VSTD::declval<_Tp&>(), _VSTD::declval<_A0&>())) type; typedef decltype(__invoke(_VSTD::declval<_Tp&>(), _VSTD::declval<_A0&>())) type;
}; };
template <class _Rp, class _Tp, class _A0> template <class _Rp, class _Tp, class _A0>
struct __invoke_return0<_Rp _Tp::*, _A0> struct __invoke_return0<_Rp _Tp::*, _A0, true>
{ {
typedef typename __apply_cv<_A0, _Rp>::type& type; typedef typename __apply_cv<_A0, _Rp>::type& type;
}; };
template <class _Rp, class _Tp, class _A0> template <class _Rp, class _Tp, class _A0>
struct __invoke_return0<_Rp _Tp::*, _A0*> struct __invoke_return0<_Rp _Tp::*, _A0*, true>
{ {
typedef typename __apply_cv<_A0, _Rp>::type& type; typedef typename __apply_cv<_A0, _Rp>::type& type;
}; };

View File

@ -1260,10 +1260,6 @@ public:
return __invoke(__f_, _VSTD::forward<_ArgTypes>(__args)...); return __invoke(__f_, _VSTD::forward<_ArgTypes>(__args)...);
} }
#else #else
typename __invoke_return<type>::type
operator() () const {
return __invoke(__f_);
}
template <class _A0> template <class _A0>
typename __invoke_return0<type, _A0>::type typename __invoke_return0<type, _A0>::type