Commit 866ed94d authored by Howard Hinnant's avatar Howard Hinnant
Browse files

Constrain __invoke functions more accurately. This fixes...

Constrain __invoke functions more accurately.  This fixes http://llvm.org/bugs/show_bug.cgi?id=15861 .

llvm-svn: 181377
parent 861b5b5a
Loading
Loading
Loading
Loading
+8 −4
Original line number Diff line number Diff line
@@ -292,7 +292,8 @@ struct __weak_result_type<_Rp (_Cp::*)(_A1, _A2, _A3...) const volatile>

// bullets 1 and 2

template <class _Fp, class _A0, class ..._Args>
template <class _Fp, class _A0, class ..._Args,
            class>
inline _LIBCPP_INLINE_VISIBILITY
auto
__invoke(_Fp&& __f, _A0&& __a0, _Args&& ...__args)
@@ -301,7 +302,8 @@ __invoke(_Fp&& __f, _A0&& __a0, _Args&& ...__args)
    return (_VSTD::forward<_A0>(__a0).*__f)(_VSTD::forward<_Args>(__args)...);
}

template <class _Fp, class _A0, class ..._Args>
template <class _Fp, class _A0, class ..._Args,
            class>
inline _LIBCPP_INLINE_VISIBILITY
auto
__invoke(_Fp&& __f, _A0&& __a0, _Args&& ...__args)
@@ -312,7 +314,8 @@ __invoke(_Fp&& __f, _A0&& __a0, _Args&& ...__args)

// bullets 3 and 4

template <class _Fp, class _A0>
template <class _Fp, class _A0,
            class>
inline _LIBCPP_INLINE_VISIBILITY
auto
__invoke(_Fp&& __f, _A0&& __a0)
@@ -321,7 +324,8 @@ __invoke(_Fp&& __f, _A0&& __a0)
    return _VSTD::forward<_A0>(__a0).*__f;
}

template <class _Fp, class _A0>
template <class _Fp, class _A0,
            class>
inline _LIBCPP_INLINE_VISIBILITY
auto
__invoke(_Fp&& __f, _A0&& __a0)
+32 −4
Original line number Diff line number Diff line
@@ -2878,13 +2878,27 @@ __invoke(__any, _Args&& ...__args)

// bullets 1 and 2

template <class _Fp, class _A0, class ..._Args>
template <class _Fp, class _A0, class ..._Args,
            class = typename enable_if
            <
                is_member_function_pointer<typename remove_reference<_Fp>::type>::value &&
                is_base_of<typename __member_pointer_traits<typename remove_reference<_Fp>::type>::_ClassType,
                           typename remove_reference<_A0>::type>::value
            >::type
         >
_LIBCPP_INLINE_VISIBILITY
auto
__invoke(_Fp&& __f, _A0&& __a0, _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
            <
                is_member_function_pointer<typename remove_reference<_Fp>::type>::value &&
                !is_base_of<typename __member_pointer_traits<typename remove_reference<_Fp>::type>::_ClassType,
                           typename remove_reference<_A0>::type>::value
            >::type
         >
_LIBCPP_INLINE_VISIBILITY
auto
__invoke(_Fp&& __f, _A0&& __a0, _Args&& ...__args)
@@ -2892,13 +2906,27 @@ __invoke(_Fp&& __f, _A0&& __a0, _Args&& ...__args)

// bullets 3 and 4

template <class _Fp, class _A0>
template <class _Fp, class _A0,
            class = typename enable_if
            <
                is_member_object_pointer<typename remove_reference<_Fp>::type>::value &&
                is_base_of<typename __member_pointer_traits<typename remove_reference<_Fp>::type>::_ClassType,
                           typename remove_reference<_A0>::type>::value
            >::type
         >
_LIBCPP_INLINE_VISIBILITY
auto
__invoke(_Fp&& __f, _A0&& __a0)
    -> decltype(_VSTD::forward<_A0>(__a0).*__f);

template <class _Fp, class _A0>
template <class _Fp, class _A0,
            class = typename enable_if
            <
                is_member_object_pointer<typename remove_reference<_Fp>::type>::value &&
                !is_base_of<typename __member_pointer_traits<typename remove_reference<_Fp>::type>::_ClassType,
                           typename remove_reference<_A0>::type>::value
            >::type
         >
_LIBCPP_INLINE_VISIBILITY
auto
__invoke(_Fp&& __f, _A0&& __a0)
+7 −0
Original line number Diff line number Diff line
@@ -28,6 +28,12 @@ struct S
typedef void (S::*PMS)(long) const;
typedef char S::*PMD;

struct wat
{
    wat& operator*() { return *this; }
    void foo();
};

int main()
{
    static_assert((std::is_same<std::result_of<S(int)>::type, short>::value), "Error!");
@@ -40,4 +46,5 @@ int main()
    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!");
    using type = std::result_of<decltype(&wat::foo)(wat)>::type;
}