[libcxx] r246977 - make common_type SFINAE-friendly and support void. Patch from Agustin Berge.

Eric Fiselier via cfe-commits cfe-commits at lists.llvm.org
Mon Sep 7 17:13:57 PDT 2015


Author: ericwf
Date: Mon Sep  7 19:13:57 2015
New Revision: 246977

URL: http://llvm.org/viewvc/llvm-project?rev=246977&view=rev
Log:
make common_type SFINAE-friendly and support void. Patch from Agustin Berge.

This patch also fixes PR22135. (https://llvm.org/bugs/show_bug.cgi?id=22135)
See the review for more information: http://reviews.llvm.org/D6964

Modified:
    libcxx/trunk/include/type_traits
    libcxx/trunk/test/std/utilities/meta/meta.trans/meta.trans.other/common_type.pass.cpp

Modified: libcxx/trunk/include/type_traits
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/type_traits?rev=246977&r1=246976&r2=246977&view=diff
==============================================================================
--- libcxx/trunk/include/type_traits (original)
+++ libcxx/trunk/include/type_traits Mon Sep  7 19:13:57 2015
@@ -1517,21 +1517,19 @@ public:
 template <class _Tp, class _Up>
 struct _LIBCPP_TYPE_VIS_ONLY common_type<_Tp, _Up, void>
 {
-private:
-#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
-    static _Tp&& __t();
-    static _Up&& __u();
-#else  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
-    static _Tp __t();
-    static _Up __u();
-#endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
-public:
-    typedef typename remove_reference<decltype(true ? __t() : __u())>::type type;
+    typedef typename decay<decltype(
+        true ? _VSTD::declval<_Tp>() : _VSTD::declval<_Up>()
+      )>::type type;
 };
 
 #else  // _LIBCPP_HAS_NO_VARIADICS
 
-template <class ..._Tp> struct common_type;
+// bullet 1 - sizeof...(Tp) == 0
+
+template <class ..._Tp>
+struct _LIBCPP_TYPE_VIS_ONLY common_type {};
+
+// bullet 2 - sizeof...(Tp) == 1
 
 template <class _Tp>
 struct _LIBCPP_TYPE_VIS_ONLY common_type<_Tp>
@@ -1539,23 +1537,46 @@ struct _LIBCPP_TYPE_VIS_ONLY common_type
     typedef typename decay<_Tp>::type type;
 };
 
+// bullet 3 - sizeof...(Tp) == 2
+
+template <class _Tp, class _Up, class = void>
+struct __common_type2 {};
+
 template <class _Tp, class _Up>
-struct _LIBCPP_TYPE_VIS_ONLY common_type<_Tp, _Up>
+struct __common_type2<_Tp, _Up,
+    typename __void_t<decltype(
+        true ? _VSTD::declval<_Tp>() : _VSTD::declval<_Up>()
+    )>::type>
 {
-private:
-    static _Tp&& __t();
-    static _Up&& __u();
-    static bool __f();
-public:
-    typedef typename decay<decltype(__f() ? __t() : __u())>::type type;
+    typedef typename decay<decltype(
+        true ? _VSTD::declval<_Tp>() : _VSTD::declval<_Up>()
+    )>::type type;
 };
 
+template <class _Tp, class _Up>
+struct _LIBCPP_TYPE_VIS_ONLY common_type<_Tp, _Up>
+    : __common_type2<_Tp, _Up> {};
+
+// bullet 4 - sizeof...(Tp) > 2
+
+template <class ...Tp> struct __common_types;
+
+template <class, class = void>
+struct __common_type_impl {};
+
 template <class _Tp, class _Up, class ..._Vp>
-struct _LIBCPP_TYPE_VIS_ONLY common_type<_Tp, _Up, _Vp...>
+struct __common_type_impl<__common_types<_Tp, _Up, _Vp...>,
+    typename __void_t<typename common_type<_Tp, _Up>::type>::type>
 {
-    typedef typename common_type<typename common_type<_Tp, _Up>::type, _Vp...>::type type;
+    typedef typename common_type<
+        typename common_type<_Tp, _Up>::type, _Vp...
+    >::type type;
 };
 
+template <class _Tp, class _Up, class ..._Vp>
+struct _LIBCPP_TYPE_VIS_ONLY common_type<_Tp, _Up, _Vp...>
+    : __common_type_impl<__common_types<_Tp, _Up, _Vp...> > {};
+
 #if _LIBCPP_STD_VER > 11
 template <class ..._Tp> using common_type_t = typename common_type<_Tp...>::type;
 #endif

Modified: libcxx/trunk/test/std/utilities/meta/meta.trans/meta.trans.other/common_type.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/meta/meta.trans/meta.trans.other/common_type.pass.cpp?rev=246977&r1=246976&r2=246977&view=diff
==============================================================================
--- libcxx/trunk/test/std/utilities/meta/meta.trans/meta.trans.other/common_type.pass.cpp (original)
+++ libcxx/trunk/test/std/utilities/meta/meta.trans/meta.trans.other/common_type.pass.cpp Mon Sep  7 19:13:57 2015
@@ -13,11 +13,39 @@
 
 #include <type_traits>
 
+#include "test_macros.h"
+
+struct E {};
+
+template <class T>
+struct X { explicit X(T const&){} };
+
+template <class T>
+struct S { explicit S(T const&){} };
+
+namespace std
+{
+    template <typename T>
+    struct common_type<T, ::S<T> >
+    {
+        typedef S<T> type;
+    };
+}
+
+#if TEST_STD_VER >= 11
+template <class T, class U, class = void>
+struct no_common_type : std::true_type {};
+
+template <class T, class U>
+struct no_common_type<T, U, typename std::conditional<false,
+    typename std::common_type<T, U>::type, void>::type> : std::false_type {};
+#endif // TEST_STD_VER >= 11
+
 int main()
 {
     static_assert((std::is_same<std::common_type<int>::type, int>::value), "");
     static_assert((std::is_same<std::common_type<char>::type, char>::value), "");
-#if _LIBCPP_STD_VER > 11
+#if TEST_STD_VER > 11
     static_assert((std::is_same<std::common_type_t<int>,   int>::value), "");
     static_assert((std::is_same<std::common_type_t<char>, char>::value), "");
 #endif
@@ -29,7 +57,7 @@ int main()
 
     static_assert((std::is_same<std::common_type<int,           int>::type, int>::value), "");
     static_assert((std::is_same<std::common_type<int,     const int>::type, int>::value), "");
-    
+
     static_assert((std::is_same<std::common_type<long,       const int>::type, long>::value), "");
     static_assert((std::is_same<std::common_type<const long,       int>::type, long>::value), "");
     static_assert((std::is_same<std::common_type<long,    volatile int>::type, long>::value), "");
@@ -38,15 +66,37 @@ int main()
 
     static_assert((std::is_same<std::common_type<double, char>::type, double>::value), "");
     static_assert((std::is_same<std::common_type<short, char>::type, int>::value), "");
-#if _LIBCPP_STD_VER > 11
+#if TEST_STD_VER > 11
     static_assert((std::is_same<std::common_type_t<double, char>, double>::value), "");
     static_assert((std::is_same<std::common_type_t<short, char>, int>::value), "");
 #endif
 
     static_assert((std::is_same<std::common_type<double, char, long long>::type, double>::value), "");
     static_assert((std::is_same<std::common_type<unsigned, char, long long>::type, long long>::value), "");
-#if _LIBCPP_STD_VER > 11
+#if TEST_STD_VER > 11
     static_assert((std::is_same<std::common_type_t<double, char, long long>, double>::value), "");
     static_assert((std::is_same<std::common_type_t<unsigned, char, long long>, long long>::value), "");
 #endif
+
+    static_assert((std::is_same<std::common_type<               void>::type, void>::value), "");
+    static_assert((std::is_same<std::common_type<const          void>::type, void>::value), "");
+    static_assert((std::is_same<std::common_type<      volatile void>::type, void>::value), "");
+    static_assert((std::is_same<std::common_type<const volatile void>::type, void>::value), "");
+
+    static_assert((std::is_same<std::common_type<void,       const void>::type, void>::value), "");
+    static_assert((std::is_same<std::common_type<const void,       void>::type, void>::value), "");
+    static_assert((std::is_same<std::common_type<void,    volatile void>::type, void>::value), "");
+    static_assert((std::is_same<std::common_type<volatile void,    void>::type, void>::value), "");
+    static_assert((std::is_same<std::common_type<const void, const void>::type, void>::value), "");
+
+#if TEST_STD_VER >= 11
+    static_assert((no_common_type<void, int>::value), "");
+    static_assert((no_common_type<int, void>::value), "");
+    static_assert((no_common_type<int, E>::value), "");
+    static_assert((no_common_type<int, X<int> >::value), "");
+#endif // TEST_STD_VER >= 11
+
+    static_assert((std::is_same<std::common_type<int, S<int> >::type, S<int> >::value), "");
+    static_assert((std::is_same<std::common_type<int, S<int>, S<int> >::type, S<int> >::value), "");
+    static_assert((std::is_same<std::common_type<int, int, S<int> >::type, S<int> >::value), "");
 }




More information about the cfe-commits mailing list