Hi mclow.lists, EricWF,

Implement a SFINAE-friendly `common_type` as per LWG2408 for the variadic case, 
and fixes the no-variadic case to work with `void` as per LWG1255.

http://reviews.llvm.org/D6964

Files:
  include/type_traits
  test/std/utilities/meta/meta.trans/meta.trans.other/common_type.pass.cpp

EMAIL PREFERENCES
  http://reviews.llvm.org/settings/panel/emailpreferences/
Index: include/type_traits
===================================================================
--- include/type_traits
+++ include/type_traits
@@ -1450,45 +1450,58 @@
 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 ? declval<_Tp>() : 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>
 {
     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 ? declval<_Tp>() : 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 ? declval<_Tp>() : 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;
 };
 
+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
Index: test/std/utilities/meta/meta.trans/meta.trans.other/common_type.pass.cpp
===================================================================
--- test/std/utilities/meta/meta.trans/meta.trans.other/common_type.pass.cpp
+++ test/std/utilities/meta/meta.trans/meta.trans.other/common_type.pass.cpp
@@ -13,6 +13,30 @@
 
 #include <type_traits>
 
+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;
+    };
+}
+
+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 {};
+
 int main()
 {
     static_assert((std::is_same<std::common_type<int>::type, int>::value), "");
@@ -29,7 +53,7 @@
 
     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), "");
@@ -49,4 +73,24 @@
     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), "");
+
+    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), "");
+
+    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), "");
 }
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to