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

Howard Hinnant hhinnant at apple.com
Tue May 7 16:40:13 PDT 2013


Author: hhinnant
Date: Tue May  7 18:40:12 2013
New Revision: 181377

URL: http://llvm.org/viewvc/llvm-project?rev=181377&view=rev
Log:
Constrain __invoke functions more accurately.  This fixes http://llvm.org/bugs/show_bug.cgi?id=15861 .

Modified:
    libcxx/trunk/include/__functional_base
    libcxx/trunk/include/type_traits
    libcxx/trunk/test/utilities/meta/meta.trans/meta.trans.other/result_of.pass.cpp

Modified: libcxx/trunk/include/__functional_base
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/__functional_base?rev=181377&r1=181376&r2=181377&view=diff
==============================================================================
--- libcxx/trunk/include/__functional_base (original)
+++ libcxx/trunk/include/__functional_base Tue May  7 18:40:12 2013
@@ -292,7 +292,8 @@ struct __weak_result_type<_Rp (_Cp::*)(_
 
 // 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&&
     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&&
 
 // 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)

Modified: libcxx/trunk/include/type_traits
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/type_traits?rev=181377&r1=181376&r2=181377&view=diff
==============================================================================
--- libcxx/trunk/include/type_traits (original)
+++ libcxx/trunk/include/type_traits Tue May  7 18:40:12 2013
@@ -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&&
 
 // 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)

Modified: libcxx/trunk/test/utilities/meta/meta.trans/meta.trans.other/result_of.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/utilities/meta/meta.trans/meta.trans.other/result_of.pass.cpp?rev=181377&r1=181376&r2=181377&view=diff
==============================================================================
--- libcxx/trunk/test/utilities/meta/meta.trans/meta.trans.other/result_of.pass.cpp (original)
+++ libcxx/trunk/test/utilities/meta/meta.trans/meta.trans.other/result_of.pass.cpp Tue May  7 18:40:12 2013
@@ -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;
 }





More information about the cfe-commits mailing list