Redesign of result_of to handle reference-qualified member functions

llvm-svn: 131407
This commit is contained in:
Howard Hinnant 2011-05-16 16:17:21 +00:00
parent e90c1cb221
commit 15c34d48ba
2 changed files with 329 additions and 53 deletions

View File

@ -1419,11 +1419,239 @@ public:
>::type type;
};
template <class _MP, bool _IsMemberFuctionPtr, bool _IsMemberObjectPtr>
struct __member_pointer_traits_imp
{
};
#ifndef _LIBCPP_HAS_NO_VARIADICS
template <class _R, class _Class, class ..._Param>
struct __member_pointer_traits_imp<_R (_Class::*)(_Param...), true, false>
{
typedef _Class _ClassType;
typedef _R _ReturnType;
};
template <class _R, class _Class, class ..._Param>
struct __member_pointer_traits_imp<_R (_Class::*)(_Param...) const, true, false>
{
typedef _Class const _ClassType;
typedef _R _ReturnType;
};
template <class _R, class _Class, class ..._Param>
struct __member_pointer_traits_imp<_R (_Class::*)(_Param...) volatile, true, false>
{
typedef _Class volatile _ClassType;
typedef _R _ReturnType;
};
template <class _R, class _Class, class ..._Param>
struct __member_pointer_traits_imp<_R (_Class::*)(_Param...) const volatile, true, false>
{
typedef _Class const volatile _ClassType;
typedef _R _ReturnType;
};
#if __has_feature(cxx_reference_qualified_functions)
template <class _R, class _Class, class ..._Param>
struct __member_pointer_traits_imp<_R (_Class::*)(_Param...) &, true, false>
{
typedef _Class& _ClassType;
typedef _R _ReturnType;
};
template <class _R, class _Class, class ..._Param>
struct __member_pointer_traits_imp<_R (_Class::*)(_Param...) const&, true, false>
{
typedef _Class const& _ClassType;
typedef _R _ReturnType;
};
template <class _R, class _Class, class ..._Param>
struct __member_pointer_traits_imp<_R (_Class::*)(_Param...) volatile&, true, false>
{
typedef _Class volatile& _ClassType;
typedef _R _ReturnType;
};
template <class _R, class _Class, class ..._Param>
struct __member_pointer_traits_imp<_R (_Class::*)(_Param...) const volatile&, true, false>
{
typedef _Class const volatile& _ClassType;
typedef _R _ReturnType;
};
template <class _R, class _Class, class ..._Param>
struct __member_pointer_traits_imp<_R (_Class::*)(_Param...) &&, true, false>
{
typedef _Class&& _ClassType;
typedef _R _ReturnType;
};
template <class _R, class _Class, class ..._Param>
struct __member_pointer_traits_imp<_R (_Class::*)(_Param...) const&&, true, false>
{
typedef _Class const&& _ClassType;
typedef _R _ReturnType;
};
template <class _R, class _Class, class ..._Param>
struct __member_pointer_traits_imp<_R (_Class::*)(_Param...) volatile&&, true, false>
{
typedef _Class volatile&& _ClassType;
typedef _R _ReturnType;
};
template <class _R, class _Class, class ..._Param>
struct __member_pointer_traits_imp<_R (_Class::*)(_Param...) const volatile&&, true, false>
{
typedef _Class const volatile&& _ClassType;
typedef _R _ReturnType;
};
#endif // __has_feature(cxx_reference_qualified_functions)
#else // _LIBCPP_HAS_NO_VARIADICS
template <class _R, class _Class>
struct __member_pointer_traits_imp<_R (_Class::*)(), true, false>
{
typedef _Class _ClassType;
typedef _R _ReturnType;
};
template <class _R, class _Class, class _P0>
struct __member_pointer_traits_imp<_R (_Class::*)(_P0), true, false>
{
typedef _Class _ClassType;
typedef _R _ReturnType;
};
template <class _R, class _Class, class _P0, class _P1>
struct __member_pointer_traits_imp<_R (_Class::*)(_P0, _P1), true, false>
{
typedef _Class _ClassType;
typedef _R _ReturnType;
};
template <class _R, class _Class, class _P0, class _P1, class _P2>
struct __member_pointer_traits_imp<_R (_Class::*)(_P0, _P1, _P2), true, false>
{
typedef _Class _ClassType;
typedef _R _ReturnType;
};
template <class _R, class _Class>
struct __member_pointer_traits_imp<_R (_Class::*)() const, true, false>
{
typedef _Class const _ClassType;
typedef _R _ReturnType;
};
template <class _R, class _Class, class _P0>
struct __member_pointer_traits_imp<_R (_Class::*)(_P0) const, true, false>
{
typedef _Class const _ClassType;
typedef _R _ReturnType;
};
template <class _R, class _Class, class _P0, class _P1>
struct __member_pointer_traits_imp<_R (_Class::*)(_P0, _P1) const, true, false>
{
typedef _Class const _ClassType;
typedef _R _ReturnType;
};
template <class _R, class _Class, class _P0, class _P1, class _P2>
struct __member_pointer_traits_imp<_R (_Class::*)(_P0, _P1, _P2) const, true, false>
{
typedef _Class const _ClassType;
typedef _R _ReturnType;
};
template <class _R, class _Class>
struct __member_pointer_traits_imp<_R (_Class::*)() volatile, true, false>
{
typedef _Class volatile _ClassType;
typedef _R _ReturnType;
};
template <class _R, class _Class, class _P0>
struct __member_pointer_traits_imp<_R (_Class::*)(_P0) volatile, true, false>
{
typedef _Class volatile _ClassType;
typedef _R _ReturnType;
};
template <class _R, class _Class, class _P0, class _P1>
struct __member_pointer_traits_imp<_R (_Class::*)(_P0, _P1) volatile, true, false>
{
typedef _Class volatile _ClassType;
typedef _R _ReturnType;
};
template <class _R, class _Class, class _P0, class _P1, class _P2>
struct __member_pointer_traits_imp<_R (_Class::*)(_P0, _P1, _P2) volatile, true, false>
{
typedef _Class volatile _ClassType;
typedef _R _ReturnType;
};
template <class _R, class _Class>
struct __member_pointer_traits_imp<_R (_Class::*)() const volatile, true, false>
{
typedef _Class const volatile _ClassType;
typedef _R _ReturnType;
};
template <class _R, class _Class, class _P0>
struct __member_pointer_traits_imp<_R (_Class::*)(_P0) const volatile, true, false>
{
typedef _Class const volatile _ClassType;
typedef _R _ReturnType;
};
template <class _R, class _Class, class _P0, class _P1>
struct __member_pointer_traits_imp<_R (_Class::*)(_P0, _P1) const volatile, true, false>
{
typedef _Class const volatile _ClassType;
typedef _R _ReturnType;
};
template <class _R, class _Class, class _P0, class _P1, class _P2>
struct __member_pointer_traits_imp<_R (_Class::*)(_P0, _P1, _P2) const volatile, true, false>
{
typedef _Class const volatile _ClassType;
typedef _R _ReturnType;
};
#endif // _LIBCPP_HAS_NO_VARIADICS
template <class _R, class _Class>
struct __member_pointer_traits_imp<_R _Class::*, false, true>
{
typedef _Class _ClassType;
typedef _R _ReturnType;
};
template <class _MP>
struct __member_pointer_traits
: public __member_pointer_traits_imp<_MP,
is_member_function_pointer<_MP>::value,
is_member_object_pointer<_MP>::value>
{
// typedef ... _ClassType;
// typedef ... _ReturnType;
};
// result_of
template <class> class result_of;
template <class _Fn, bool>
template <class _Fn, bool, bool>
class __result_of
{
};
@ -1431,39 +1659,21 @@ class __result_of
#ifndef _LIBCPP_HAS_NO_VARIADICS
template <class _Fn, class ..._ArgTypes>
class __result_of<_Fn(_ArgTypes...), true>
class __result_of<_Fn(_ArgTypes...), true, false>
{
public:
typedef decltype(declval<_Fn>()(declval<_ArgTypes>()...)) type;
};
template <class _MP, class _Tp, bool _IsMemberFunctionPtr, class ..._Args>
struct __result_of_mp {};
template <class _MP, class _Tp, bool _IsMemberFunctionPtr>
struct __result_of_mp;
// member function pointer
template <class _R, class _Class, class _Tp, class ..._Params, class ..._Args>
struct __result_of_mp<_R (_Class::*)(_Params...), _Tp, true, _Args...>
template <class _MP, class _Tp>
struct __result_of_mp<_MP, _Tp, true>
: public common_type<typename __member_pointer_traits<_MP>::_ReturnType>
{
typedef _R type;
};
template <class _R, class _Class, class _Tp, class ..._Params, class ..._Args>
struct __result_of_mp<_R (_Class::*)(_Params...) const, _Tp, true, _Args...>
{
typedef _R type;
};
template <class _R, class _Class, class _Tp, class ..._Params, class ..._Args>
struct __result_of_mp<_R (_Class::*)(_Params...) volatile, _Tp, true, _Args...>
{
typedef _R type;
};
template <class _R, class _Class, class _Tp, class ..._Params, class ..._Args>
struct __result_of_mp<_R (_Class::*)(_Params...) const volatile, _Tp, true, _Args...>
{
typedef _R type;
};
// member data pointer
@ -1474,7 +1684,7 @@ struct __result_of_mdp;
template <class _R, class _Class, class _Tp>
struct __result_of_mdp<_R _Class::*, _Tp, false>
{
typedef typename __apply_cv<decltype(*_STD::declval<_Tp>()), _R>::type type;
typedef typename __apply_cv<decltype(*_STD::declval<_Tp>()), _R>::type&& type;
};
template <class _R, class _Class, class _Tp>
@ -1491,9 +1701,10 @@ struct __result_of_mp<_R _Class::*, _Tp, false>
};
template <class _Fn, class _Tp, class ..._ArgTypes>
class __result_of<_Fn(_Tp, _ArgTypes...), false> // _Fn must be member pointer
: public __result_of_mp<_Fn, _Tp, is_member_function_pointer<_Fn>::value,
_ArgTypes...>
class __result_of<_Fn(_Tp, _ArgTypes...), false, true> // _Fn must be member pointer
: public __result_of_mp<typename remove_reference<_Fn>::type,
_Tp,
is_member_function_pointer<typename remove_reference<_Fn>::type>::value>
{
};
@ -1503,10 +1714,8 @@ template <class _Fn, class ..._ArgTypes>
class _LIBCPP_VISIBLE result_of<_Fn(_ArgTypes...)>
: public __result_of<_Fn(_ArgTypes...),
is_class<typename remove_reference<_Fn>::type>::value ||
is_function<typename remove_pointer<
typename remove_reference<_Fn>::type
>::type
>::value
is_function<typename remove_reference<_Fn>::type>::value,
is_member_pointer<typename remove_reference<_Fn>::type>::value
>
{
};
@ -1514,41 +1723,110 @@ class _LIBCPP_VISIBLE result_of<_Fn(_ArgTypes...)>
#else // _LIBCPP_HAS_NO_VARIADICS
template <class _Fn>
class __result_of<_Fn(), true>
class __result_of<_Fn(), true, false>
{
public:
typedef decltype(declval<_Fn>()()) type;
};
template <class _Fn, class _A0>
class __result_of<_Fn(_A0), true>
class __result_of<_Fn(_A0), true, false>
{
public:
typedef decltype(declval<_Fn>()(declval<_A0>())) type;
};
template <class _Fn, class _A0, class _A1>
class __result_of<_Fn(_A0, _A1), true>
class __result_of<_Fn(_A0, _A1), true, false>
{
public:
typedef decltype(declval<_Fn>()(declval<_A0>(), declval<_A1>())) type;
};
template <class _Fn, class _A0, class _A1, class _A2>
class __result_of<_Fn(_A0, _A1, _A2), true>
class __result_of<_Fn(_A0, _A1, _A2), true, false>
{
public:
typedef decltype(declval<_Fn>()(declval<_A0>(), declval<_A1>(), declval<_A2>())) type;
};
template <class _MP, class _Tp, bool _IsMemberFunctionPtr>
struct __result_of_mp;
// member function pointer
template <class _MP, class _Tp>
struct __result_of_mp<_MP, _Tp, true>
: public common_type<typename __member_pointer_traits<_MP>::_ReturnType>
{
};
// member data pointer
template <class _MP, class _Tp, bool>
struct __result_of_mdp;
template <class _R, class _Class, class _Tp>
struct __result_of_mdp<_R _Class::*, _Tp, false>
{
typedef typename __apply_cv<decltype(*_STD::declval<_Tp>()), _R>::type& type;
};
template <class _R, class _Class, class _Tp>
struct __result_of_mdp<_R _Class::*, _Tp, true>
{
typedef typename __apply_cv<_Tp, _R>::type& type;
};
template <class _R, class _Class, class _Tp>
struct __result_of_mp<_R _Class::*, _Tp, false>
: public __result_of_mdp<_R _Class::*, _Tp,
is_base_of<_Class, typename remove_reference<_Tp>::type>::value>
{
};
template <class _Fn, class _Tp>
class __result_of<_Fn(_Tp), false, true> // _Fn must be member pointer
: public __result_of_mp<typename remove_reference<_Fn>::type,
_Tp,
is_member_function_pointer<typename remove_reference<_Fn>::type>::value>
{
};
template <class _Fn, class _Tp, class _A0>
class __result_of<_Fn(_Tp, _A0), false, true> // _Fn must be member pointer
: public __result_of_mp<typename remove_reference<_Fn>::type,
_Tp,
is_member_function_pointer<typename remove_reference<_Fn>::type>::value>
{
};
template <class _Fn, class _Tp, class _A0, class _A1>
class __result_of<_Fn(_Tp, _A0, _A1), false, true> // _Fn must be member pointer
: public __result_of_mp<typename remove_reference<_Fn>::type,
_Tp,
is_member_function_pointer<typename remove_reference<_Fn>::type>::value>
{
};
template <class _Fn, class _Tp, class _A0, class _A1, class _A2>
class __result_of<_Fn(_Tp, _A0, _A1, _A2), false, true> // _Fn must be member pointer
: public __result_of_mp<typename remove_reference<_Fn>::type,
_Tp,
is_member_function_pointer<typename remove_reference<_Fn>::type>::value>
{
};
// result_of
template <class _Fn>
class _LIBCPP_VISIBLE result_of<_Fn()>
: public __result_of<_Fn(),
is_class<typename remove_reference<_Fn>::type>::value ||
is_function<typename remove_pointer<
typename remove_reference<_Fn>::type
>::type
>::value
is_function<typename remove_reference<_Fn>::type>::value,
is_member_pointer<typename remove_reference<_Fn>::type>::value
>
{
};
@ -1557,10 +1835,8 @@ template <class _Fn, class _A0>
class _LIBCPP_VISIBLE result_of<_Fn(_A0)>
: public __result_of<_Fn(_A0),
is_class<typename remove_reference<_Fn>::type>::value ||
is_function<typename remove_pointer<
typename remove_reference<_Fn>::type
>::type
>::value
is_function<typename remove_reference<_Fn>::type>::value,
is_member_pointer<typename remove_reference<_Fn>::type>::value
>
{
};
@ -1569,10 +1845,8 @@ template <class _Fn, class _A0, class _A1>
class _LIBCPP_VISIBLE result_of<_Fn(_A0, _A1)>
: public __result_of<_Fn(_A0, _A1),
is_class<typename remove_reference<_Fn>::type>::value ||
is_function<typename remove_pointer<
typename remove_reference<_Fn>::type
>::type
>::value
is_function<typename remove_reference<_Fn>::type>::value,
is_member_pointer<typename remove_reference<_Fn>::type>::value
>
{
};
@ -1581,10 +1855,8 @@ template <class _Fn, class _A0, class _A1, class _A2>
class _LIBCPP_VISIBLE result_of<_Fn(_A0, _A1, _A2)>
: public __result_of<_Fn(_A0, _A1, _A2),
is_class<typename remove_reference<_Fn>::type>::value ||
is_function<typename remove_pointer<
typename remove_reference<_Fn>::type
>::type
>::value
is_function<typename remove_reference<_Fn>::type>::value,
is_member_pointer<typename remove_reference<_Fn>::type>::value
>
{
};

View File

@ -34,6 +34,10 @@ int main()
static_assert((std::is_same<std::result_of<S&(unsigned char, int&)>::type, double>::value), "Error!");
static_assert((std::is_same<std::result_of<PF1()>::type, bool>::value), "Error!");
static_assert((std::is_same<std::result_of<PMS(std::unique_ptr<S>, int)>::type, void>::value), "Error!");
static_assert((std::is_same<std::result_of<PMS(S, int)>::type, void>::value), "Error!");
static_assert((std::is_same<std::result_of<PMS(const S&, int)>::type, void>::value), "Error!");
#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
static_assert((std::is_same<std::result_of<PMD(S)>::type, char&&>::value), "Error!");
#endif
static_assert((std::is_same<std::result_of<PMD(const S*)>::type, const char&>::value), "Error!");
}