12ddf2cbd2
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. git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@243368 91177308-0d34-0410-b5e6-96231b3b80d8
531 lines
13 KiB
C++
531 lines
13 KiB
C++
// -*- C++ -*-
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is dual licensed under the MIT and the University of Illinois Open
|
|
// Source Licenses. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef _LIBCPP_FUNCTIONAL_BASE_03
|
|
#define _LIBCPP_FUNCTIONAL_BASE_03
|
|
|
|
// manual variadic expansion for <functional>
|
|
|
|
// __invoke
|
|
// first bullet
|
|
|
|
template <class _Rp, class _Tp, class _T1>
|
|
inline _LIBCPP_INLINE_VISIBILITY
|
|
typename enable_if
|
|
<
|
|
is_base_of<_Tp, typename remove_reference<_T1>::type>::value,
|
|
_Rp
|
|
>::type
|
|
__invoke(_Rp (_Tp::*__f)(), _T1& __t1)
|
|
{
|
|
return (__t1.*__f)();
|
|
}
|
|
|
|
template <class _Rp, class _Tp, class _T1, class _A0>
|
|
inline _LIBCPP_INLINE_VISIBILITY
|
|
typename enable_if
|
|
<
|
|
is_base_of<_Tp, typename remove_reference<_T1>::type>::value,
|
|
_Rp
|
|
>::type
|
|
__invoke(_Rp (_Tp::*__f)(_A0), _T1& __t1, _A0& __a0)
|
|
{
|
|
return (__t1.*__f)(__a0);
|
|
}
|
|
|
|
template <class _Rp, class _Tp, class _T1, class _A0, class _A1>
|
|
inline _LIBCPP_INLINE_VISIBILITY
|
|
typename enable_if
|
|
<
|
|
is_base_of<_Tp, typename remove_reference<_T1>::type>::value,
|
|
_Rp
|
|
>::type
|
|
__invoke(_Rp (_Tp::*__f)(_A0, _A1), _T1& __t1, _A0& __a0, _A1& __a1)
|
|
{
|
|
return (__t1.*__f)(__a0, __a1);
|
|
}
|
|
|
|
template <class _Rp, class _Tp, class _T1, class _A0, class _A1, class _A2>
|
|
inline _LIBCPP_INLINE_VISIBILITY
|
|
typename enable_if
|
|
<
|
|
is_base_of<_Tp, typename remove_reference<_T1>::type>::value,
|
|
_Rp
|
|
>::type
|
|
__invoke(_Rp (_Tp::*__f)(_A0, _A1, _A2), _T1& __t1, _A0& __a0, _A1& __a1, _A2& __a2)
|
|
{
|
|
return (__t1.*__f)(__a0, __a1, __a2);
|
|
}
|
|
|
|
template <class _Rp, class _Tp, class _T1>
|
|
inline _LIBCPP_INLINE_VISIBILITY
|
|
typename enable_if
|
|
<
|
|
is_base_of<_Tp, typename remove_reference<_T1>::type>::value,
|
|
_Rp
|
|
>::type
|
|
__invoke(_Rp (_Tp::*__f)() const, _T1& __t1)
|
|
{
|
|
return (__t1.*__f)();
|
|
}
|
|
|
|
template <class _Rp, class _Tp, class _T1, class _A0>
|
|
inline _LIBCPP_INLINE_VISIBILITY
|
|
typename enable_if
|
|
<
|
|
is_base_of<_Tp, typename remove_reference<_T1>::type>::value,
|
|
_Rp
|
|
>::type
|
|
__invoke(_Rp (_Tp::*__f)(_A0) const, _T1& __t1, _A0& __a0)
|
|
{
|
|
return (__t1.*__f)(__a0);
|
|
}
|
|
|
|
template <class _Rp, class _Tp, class _T1, class _A0, class _A1>
|
|
inline _LIBCPP_INLINE_VISIBILITY
|
|
typename enable_if
|
|
<
|
|
is_base_of<_Tp, typename remove_reference<_T1>::type>::value,
|
|
_Rp
|
|
>::type
|
|
__invoke(_Rp (_Tp::*__f)(_A0, _A1) const, _T1& __t1, _A0& __a0, _A1& __a1)
|
|
{
|
|
return (__t1.*__f)(__a0, __a1);
|
|
}
|
|
|
|
template <class _Rp, class _Tp, class _T1, class _A0, class _A1, class _A2>
|
|
inline _LIBCPP_INLINE_VISIBILITY
|
|
typename enable_if
|
|
<
|
|
is_base_of<_Tp, typename remove_reference<_T1>::type>::value,
|
|
_Rp
|
|
>::type
|
|
__invoke(_Rp (_Tp::*__f)(_A0, _A1, _A2) const, _T1& __t1, _A0& __a0, _A1& __a1, _A2& __a2)
|
|
{
|
|
return (__t1.*__f)(__a0, __a1, __a2);
|
|
}
|
|
|
|
template <class _Rp, class _Tp, class _T1>
|
|
inline _LIBCPP_INLINE_VISIBILITY
|
|
typename enable_if
|
|
<
|
|
is_base_of<_Tp, typename remove_reference<_T1>::type>::value,
|
|
_Rp
|
|
>::type
|
|
__invoke(_Rp (_Tp::*__f)() volatile, _T1& __t1)
|
|
{
|
|
return (__t1.*__f)();
|
|
}
|
|
|
|
template <class _Rp, class _Tp, class _T1, class _A0>
|
|
inline _LIBCPP_INLINE_VISIBILITY
|
|
typename enable_if
|
|
<
|
|
is_base_of<_Tp, typename remove_reference<_T1>::type>::value,
|
|
_Rp
|
|
>::type
|
|
__invoke(_Rp (_Tp::*__f)(_A0) volatile, _T1& __t1, _A0& __a0)
|
|
{
|
|
return (__t1.*__f)(__a0);
|
|
}
|
|
|
|
template <class _Rp, class _Tp, class _T1, class _A0, class _A1>
|
|
inline _LIBCPP_INLINE_VISIBILITY
|
|
typename enable_if
|
|
<
|
|
is_base_of<_Tp, typename remove_reference<_T1>::type>::value,
|
|
_Rp
|
|
>::type
|
|
__invoke(_Rp (_Tp::*__f)(_A0, _A1) volatile, _T1& __t1, _A0& __a0, _A1& __a1)
|
|
{
|
|
return (__t1.*__f)(__a0, __a1);
|
|
}
|
|
|
|
template <class _Rp, class _Tp, class _T1, class _A0, class _A1, class _A2>
|
|
inline _LIBCPP_INLINE_VISIBILITY
|
|
typename enable_if
|
|
<
|
|
is_base_of<_Tp, typename remove_reference<_T1>::type>::value,
|
|
_Rp
|
|
>::type
|
|
__invoke(_Rp (_Tp::*__f)(_A0, _A1, _A2) volatile, _T1& __t1, _A0& __a0, _A1& __a1, _A2& __a2)
|
|
{
|
|
return (__t1.*__f)(__a0, __a1, __a2);
|
|
}
|
|
|
|
template <class _Rp, class _Tp, class _T1>
|
|
inline _LIBCPP_INLINE_VISIBILITY
|
|
typename enable_if
|
|
<
|
|
is_base_of<_Tp, typename remove_reference<_T1>::type>::value,
|
|
_Rp
|
|
>::type
|
|
__invoke(_Rp (_Tp::*__f)() const volatile, _T1& __t1)
|
|
{
|
|
return (__t1.*__f)();
|
|
}
|
|
|
|
template <class _Rp, class _Tp, class _T1, class _A0>
|
|
inline _LIBCPP_INLINE_VISIBILITY
|
|
typename enable_if
|
|
<
|
|
is_base_of<_Tp, typename remove_reference<_T1>::type>::value,
|
|
_Rp
|
|
>::type
|
|
__invoke(_Rp (_Tp::*__f)(_A0) const volatile, _T1& __t1, _A0& __a0)
|
|
{
|
|
return (__t1.*__f)(__a0);
|
|
}
|
|
|
|
template <class _Rp, class _Tp, class _T1, class _A0, class _A1>
|
|
inline _LIBCPP_INLINE_VISIBILITY
|
|
typename enable_if
|
|
<
|
|
is_base_of<_Tp, typename remove_reference<_T1>::type>::value,
|
|
_Rp
|
|
>::type
|
|
__invoke(_Rp (_Tp::*__f)(_A0, _A1) const volatile, _T1& __t1, _A0& __a0, _A1& __a1)
|
|
{
|
|
return (__t1.*__f)(__a0, __a1);
|
|
}
|
|
|
|
template <class _Rp, class _Tp, class _T1, class _A0, class _A1, class _A2>
|
|
inline _LIBCPP_INLINE_VISIBILITY
|
|
typename enable_if
|
|
<
|
|
is_base_of<_Tp, typename remove_reference<_T1>::type>::value,
|
|
_Rp
|
|
>::type
|
|
__invoke(_Rp (_Tp::*__f)(_A0, _A1, _A2) const volatile, _T1& __t1, _A0& __a0, _A1& __a1, _A2& __a2)
|
|
{
|
|
return (__t1.*__f)(__a0, __a1, __a2);
|
|
}
|
|
|
|
// second bullet
|
|
|
|
template <class _Rp, class _Tp, class _T1>
|
|
inline _LIBCPP_INLINE_VISIBILITY
|
|
typename enable_if
|
|
<
|
|
!is_base_of<_Tp, typename remove_reference<_T1>::type>::value,
|
|
_Rp
|
|
>::type
|
|
__invoke(_Rp (_Tp::*__f)(), _T1 __t1)
|
|
{
|
|
return ((*__t1).*__f)();
|
|
}
|
|
|
|
template <class _Rp, class _Tp, class _T1, class _A0>
|
|
inline _LIBCPP_INLINE_VISIBILITY
|
|
typename enable_if
|
|
<
|
|
!is_base_of<_Tp, typename remove_reference<_T1>::type>::value,
|
|
_Rp
|
|
>::type
|
|
__invoke(_Rp (_Tp::*__f)(_A0), _T1 __t1, _A0& __a0)
|
|
{
|
|
return ((*__t1).*__f)(__a0);
|
|
}
|
|
|
|
template <class _Rp, class _Tp, class _T1, class _A0, class _A1>
|
|
inline _LIBCPP_INLINE_VISIBILITY
|
|
typename enable_if
|
|
<
|
|
!is_base_of<_Tp, typename remove_reference<_T1>::type>::value,
|
|
_Rp
|
|
>::type
|
|
__invoke(_Rp (_Tp::*__f)(_A0, _A1), _T1 __t1, _A0& __a0, _A1& __a1)
|
|
{
|
|
return ((*__t1).*__f)(__a0, __a1);
|
|
}
|
|
|
|
template <class _Rp, class _Tp, class _T1, class _A0, class _A1, class _A2>
|
|
inline _LIBCPP_INLINE_VISIBILITY
|
|
typename enable_if
|
|
<
|
|
!is_base_of<_Tp, typename remove_reference<_T1>::type>::value,
|
|
_Rp
|
|
>::type
|
|
__invoke(_Rp (_Tp::*__f)(_A0, _A1, _A2), _T1 __t1, _A0& __a0, _A1& __a1, _A2& __a2)
|
|
{
|
|
return ((*__t1).*__f)(__a0, __a1, __a2);
|
|
}
|
|
|
|
template <class _Rp, class _Tp, class _T1>
|
|
inline _LIBCPP_INLINE_VISIBILITY
|
|
typename enable_if
|
|
<
|
|
!is_base_of<_Tp, typename remove_reference<_T1>::type>::value,
|
|
_Rp
|
|
>::type
|
|
__invoke(_Rp (_Tp::*__f)() const, _T1 __t1)
|
|
{
|
|
return ((*__t1).*__f)();
|
|
}
|
|
|
|
template <class _Rp, class _Tp, class _T1, class _A0>
|
|
inline _LIBCPP_INLINE_VISIBILITY
|
|
typename enable_if
|
|
<
|
|
!is_base_of<_Tp, typename remove_reference<_T1>::type>::value,
|
|
_Rp
|
|
>::type
|
|
__invoke(_Rp (_Tp::*__f)(_A0) const, _T1 __t1, _A0& __a0)
|
|
{
|
|
return ((*__t1).*__f)(__a0);
|
|
}
|
|
|
|
template <class _Rp, class _Tp, class _T1, class _A0, class _A1>
|
|
inline _LIBCPP_INLINE_VISIBILITY
|
|
typename enable_if
|
|
<
|
|
!is_base_of<_Tp, typename remove_reference<_T1>::type>::value,
|
|
_Rp
|
|
>::type
|
|
__invoke(_Rp (_Tp::*__f)(_A0, _A1) const, _T1 __t1, _A0& __a0, _A1& __a1)
|
|
{
|
|
return ((*__t1).*__f)(__a0, __a1);
|
|
}
|
|
|
|
template <class _Rp, class _Tp, class _T1, class _A0, class _A1, class _A2>
|
|
inline _LIBCPP_INLINE_VISIBILITY
|
|
typename enable_if
|
|
<
|
|
!is_base_of<_Tp, typename remove_reference<_T1>::type>::value,
|
|
_Rp
|
|
>::type
|
|
__invoke(_Rp (_Tp::*__f)(_A0, _A1, _A2) const, _T1 __t1, _A0& __a0, _A1& __a1, _A2& __a2)
|
|
{
|
|
return ((*__t1).*__f)(__a0, __a1, __a2);
|
|
}
|
|
|
|
template <class _Rp, class _Tp, class _T1>
|
|
inline _LIBCPP_INLINE_VISIBILITY
|
|
typename enable_if
|
|
<
|
|
!is_base_of<_Tp, typename remove_reference<_T1>::type>::value,
|
|
_Rp
|
|
>::type
|
|
__invoke(_Rp (_Tp::*__f)() volatile, _T1 __t1)
|
|
{
|
|
return ((*__t1).*__f)();
|
|
}
|
|
|
|
template <class _Rp, class _Tp, class _T1, class _A0>
|
|
inline _LIBCPP_INLINE_VISIBILITY
|
|
typename enable_if
|
|
<
|
|
!is_base_of<_Tp, typename remove_reference<_T1>::type>::value,
|
|
_Rp
|
|
>::type
|
|
__invoke(_Rp (_Tp::*__f)(_A0) volatile, _T1 __t1, _A0& __a0)
|
|
{
|
|
return ((*__t1).*__f)(__a0);
|
|
}
|
|
|
|
template <class _Rp, class _Tp, class _T1, class _A0, class _A1>
|
|
inline _LIBCPP_INLINE_VISIBILITY
|
|
typename enable_if
|
|
<
|
|
!is_base_of<_Tp, typename remove_reference<_T1>::type>::value,
|
|
_Rp
|
|
>::type
|
|
__invoke(_Rp (_Tp::*__f)(_A0, _A1) volatile, _T1 __t1, _A0& __a0, _A1& __a1)
|
|
{
|
|
return ((*__t1).*__f)(__a0, __a1);
|
|
}
|
|
|
|
template <class _Rp, class _Tp, class _T1, class _A0, class _A1, class _A2>
|
|
inline _LIBCPP_INLINE_VISIBILITY
|
|
typename enable_if
|
|
<
|
|
!is_base_of<_Tp, typename remove_reference<_T1>::type>::value,
|
|
_Rp
|
|
>::type
|
|
__invoke(_Rp (_Tp::*__f)(_A0, _A1, _A2) volatile, _T1 __t1, _A0& __a0, _A1& __a1, _A2& __a2)
|
|
{
|
|
return ((*__t1).*__f)(__a0, __a1, __a2);
|
|
}
|
|
|
|
template <class _Rp, class _Tp, class _T1>
|
|
inline _LIBCPP_INLINE_VISIBILITY
|
|
typename enable_if
|
|
<
|
|
!is_base_of<_Tp, typename remove_reference<_T1>::type>::value,
|
|
_Rp
|
|
>::type
|
|
__invoke(_Rp (_Tp::*__f)() const volatile, _T1 __t1)
|
|
{
|
|
return ((*__t1).*__f)();
|
|
}
|
|
|
|
template <class _Rp, class _Tp, class _T1, class _A0>
|
|
inline _LIBCPP_INLINE_VISIBILITY
|
|
typename enable_if
|
|
<
|
|
!is_base_of<_Tp, typename remove_reference<_T1>::type>::value,
|
|
_Rp
|
|
>::type
|
|
__invoke(_Rp (_Tp::*__f)(_A0) const volatile, _T1 __t1, _A0& __a0)
|
|
{
|
|
return ((*__t1).*__f)(__a0);
|
|
}
|
|
|
|
template <class _Rp, class _Tp, class _T1, class _A0, class _A1>
|
|
inline _LIBCPP_INLINE_VISIBILITY
|
|
typename enable_if
|
|
<
|
|
!is_base_of<_Tp, typename remove_reference<_T1>::type>::value,
|
|
_Rp
|
|
>::type
|
|
__invoke(_Rp (_Tp::*__f)(_A0, _A1) const volatile, _T1 __t1, _A0& __a0, _A1& __a1)
|
|
{
|
|
return ((*__t1).*__f)(__a0, __a1);
|
|
}
|
|
|
|
template <class _Rp, class _Tp, class _T1, class _A0, class _A1, class _A2>
|
|
inline _LIBCPP_INLINE_VISIBILITY
|
|
typename enable_if
|
|
<
|
|
!is_base_of<_Tp, typename remove_reference<_T1>::type>::value,
|
|
_Rp
|
|
>::type
|
|
__invoke(_Rp (_Tp::*__f)(_A0, _A1, _A2) const volatile, _T1 __t1, _A0& __a0, _A1& __a1, _A2& __a2)
|
|
{
|
|
return ((*__t1).*__f)(__a0, __a1, __a2);
|
|
}
|
|
|
|
// third bullet
|
|
|
|
template <class _Rp, class _Tp, class _T1>
|
|
inline _LIBCPP_INLINE_VISIBILITY
|
|
typename enable_if
|
|
<
|
|
is_base_of<_Tp, typename remove_reference<_T1>::type>::value,
|
|
typename __apply_cv<_T1, _Rp>::type&
|
|
>::type
|
|
__invoke(_Rp _Tp::* __f, _T1& __t1)
|
|
{
|
|
return __t1.*__f;
|
|
}
|
|
|
|
template <class _Rp, class _Tp>
|
|
inline _LIBCPP_INLINE_VISIBILITY
|
|
void
|
|
__invoke(_Rp _Tp::*)
|
|
{
|
|
}
|
|
|
|
// forth bullet
|
|
|
|
template <class _T1, class _Rp, bool>
|
|
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;
|
|
};
|
|
|
|
template <class _Rp, class _Tp, class _T1>
|
|
inline _LIBCPP_INLINE_VISIBILITY
|
|
typename __4th_helper<_T1, _Rp,
|
|
!is_base_of<_Tp,
|
|
typename remove_reference<_T1>::type
|
|
>::value
|
|
>::type&
|
|
__invoke(_Rp _Tp::* __f, _T1& __t1)
|
|
{
|
|
return (*__t1).*__f;
|
|
}
|
|
|
|
// fifth bullet
|
|
|
|
template <class _Fp>
|
|
inline _LIBCPP_INLINE_VISIBILITY
|
|
decltype(_VSTD::declval<_Fp&>()())
|
|
__invoke(_Fp& __f)
|
|
{
|
|
return __f();
|
|
}
|
|
|
|
template <class _Fp, class _A0>
|
|
inline _LIBCPP_INLINE_VISIBILITY
|
|
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(_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(_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 _Fp, bool = __has_result_type<__weak_result_type<_Fp> >::value>
|
|
struct __invoke_return
|
|
{
|
|
typedef typename __weak_result_type<_Fp>::result_type type;
|
|
};
|
|
|
|
template <class _Fp>
|
|
struct __invoke_return<_Fp, false>
|
|
{
|
|
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;
|
|
};
|
|
|
|
template <class _Rp, class _Tp, class _A0>
|
|
struct __invoke_return0<_Rp _Tp::*, _A0>
|
|
{
|
|
typedef typename __apply_cv<_A0, _Rp>::type& type;
|
|
};
|
|
|
|
template <class _Rp, class _Tp, class _A0>
|
|
struct __invoke_return0<_Rp _Tp::*, _A0*>
|
|
{
|
|
typedef typename __apply_cv<_A0, _Rp>::type& type;
|
|
};
|
|
|
|
template <class _Tp, class _A0, class _A1>
|
|
struct __invoke_return1
|
|
{
|
|
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;
|
|
};
|
|
|
|
#endif // _LIBCPP_FUNCTIONAL_BASE_03
|