Get C++03 __invoke working for bullet 5 of INVOKE.

This patch does a couple of things to get __invoke working for free-functions
and call objects.

1. Turn all uses of declval<Tp>() into declval<Tp&>(). The C++03 __invoke only
   supports lvalues but it will be used when the compiler supports rvalue
   references but not variadic templates. This change makes sure we don't
   generate an rvalue.

2. Call objects for bullet 5 are now passed by reference and not value. Copying
   the functor is incorrect. It will fail to compile for non-copyable functors
   and it will discard cv-qualifiers on the call object, possibly leading to the
   wrong function being called. I suspect that the reason the call object
   was originally taken by value was to support temporary call objects.
   However __invoke is only used internally and it is never given a temporary.

llvm-svn: 243368
This commit is contained in:
Eric Fiselier 2015-07-28 01:52:08 +00:00
parent 2e9f29932d
commit fda20d94e7

View File

@ -433,7 +433,7 @@ struct __4th_helper
template <class _T1, class _Rp>
struct __4th_helper<_T1, _Rp, true>
{
typedef typename __apply_cv<decltype(*_VSTD::declval<_T1>()), _Rp>::type type;
typedef typename __apply_cv<decltype(*_VSTD::declval<_T1&>()), _Rp>::type type;
};
template <class _Rp, class _Tp, class _T1>
@ -452,47 +452,36 @@ __invoke(_Rp _Tp::* __f, _T1& __t1)
template <class _Fp>
inline _LIBCPP_INLINE_VISIBILITY
decltype(declval<_Fp>()())
__invoke(_Fp __f)
decltype(_VSTD::declval<_Fp&>()())
__invoke(_Fp& __f)
{
return __f();
}
template <class _Fp, class _A0>
inline _LIBCPP_INLINE_VISIBILITY
decltype(declval<_Fp>()(declval<_A0&>()))
__invoke(_Fp __f, _A0& __a0)
decltype(_VSTD::declval<_Fp&>()(_VSTD::declval<_A0&>()))
__invoke(_Fp& __f, _A0& __a0)
{
return __f(__a0);
}
template <class _Fp, class _A0, class _A1>
inline _LIBCPP_INLINE_VISIBILITY
decltype(declval<_Fp>()(declval<_A0&>(), declval<_A1&>()))
__invoke(_Fp __f, _A0& __a0, _A1& __a1)
decltype(_VSTD::declval<_Fp&>()(_VSTD::declval<_A0&>(), _VSTD::declval<_A1&>()))
__invoke(_Fp& __f, _A0& __a0, _A1& __a1)
{
return __f(__a0, __a1);
}
template <class _Fp, class _A0, class _A1, class _A2>
inline _LIBCPP_INLINE_VISIBILITY
decltype(declval<_Fp>()(declval<_A0&>(), declval<_A1&>(), declval<_A2&>()))
__invoke(_Fp __f, _A0& __a0, _A1& __a1, _A2& __a2)
decltype(_VSTD::declval<_Fp&>()(_VSTD::declval<_A0&>(), _VSTD::declval<_A1&>(), _VSTD::declval<_A2&>()))
__invoke(_Fp& __f, _A0& __a0, _A1& __a1, _A2& __a2)
{
return __f(__a0, __a1, __a2);
}
template <class _Tp>
struct __has_type
{
private:
struct __two {char __lx; char __lxx;};
template <class _Up> static __two __test(...);
template <class _Up> static char __test(typename _Up::type* = 0);
public:
static const bool value = sizeof(__test<_Tp>(0)) == 1;
};
template <class _Fp, bool = __has_result_type<__weak_result_type<_Fp> >::value>
struct __invoke_return
{
@ -502,13 +491,13 @@ struct __invoke_return
template <class _Fp>
struct __invoke_return<_Fp, false>
{
typedef decltype(__invoke(_VSTD::declval<_Fp>())) type;
typedef decltype(__invoke(_VSTD::declval<_Fp&>())) type;
};
template <class _Tp, class _A0>
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>
@ -526,16 +515,16 @@ struct __invoke_return0<_Rp _Tp::*, _A0*>
template <class _Tp, class _A0, class _A1>
struct __invoke_return1
{
typedef decltype(__invoke(_VSTD::declval<_Tp>(), _VSTD::declval<_A0>(),
_VSTD::declval<_A1>())) type;
typedef decltype(__invoke(_VSTD::declval<_Tp&>(), _VSTD::declval<_A0&>(),
_VSTD::declval<_A1&>())) type;
};
template <class _Tp, class _A0, class _A1, class _A2>
struct __invoke_return2
{
typedef decltype(__invoke(_VSTD::declval<_Tp>(), _VSTD::declval<_A0>(),
_VSTD::declval<_A1>(),
_VSTD::declval<_A2>())) type;
typedef decltype(__invoke(_VSTD::declval<_Tp&>(), _VSTD::declval<_A0&>(),
_VSTD::declval<_A1&>(),
_VSTD::declval<_A2&>())) type;
};
#endif // _LIBCPP_FUNCTIONAL_BASE_03