diff mbox series

P0340R2 Making std::underlying_type SFINAE-friendly

Message ID 20190223212250.GA5901@redhat.com
State New
Headers show
Series P0340R2 Making std::underlying_type SFINAE-friendly | expand

Commit Message

Jonathan Wakely Feb. 23, 2019, 9:22 p.m. UTC
* include/std/type_traits (__underlying_type_impl): New helper to
	make underlying_type SFINAE-friendly.
	(underlying_type): Derive from __underlying_type_impl.
	* testsuite/20_util/underlying_type/requirements/typedefs-3.cc: New
	test.

This was just approved in Kona.

Tested powerpc64le-linux, committed to trunk.
commit fbe2d0cc1229cf5804da50e23d9dbd00ec9b1c75
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Sat Feb 23 03:32:47 2019 +0000

    P0340R2 Making std::underlying_type SFINAE-friendly
    
            * include/std/type_traits (__underlying_type_impl): New helper to
            make underlying_type SFINAE-friendly.
            (underlying_type): Derive from __underlying_type_impl.
            * testsuite/20_util/underlying_type/requirements/typedefs-3.cc: New
            test.
diff mbox series

Patch

diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits
index 993967244ff..977ca0e1350 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -2176,12 +2176,21 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
                common_type<_Tp, _Up>>::type, _Vp...>::type
     { };
 
+  template<typename _Tp, bool = is_enum<_Tp>::value>
+    struct __underlying_type_impl
+    {
+      using type = __underlying_type(_Tp);
+    };
+
+  template<typename _Tp>
+    struct __underlying_type_impl<_Tp, false>
+    { };
+
   /// The underlying type of an enum.
   template<typename _Tp>
     struct underlying_type
-    {
-      typedef __underlying_type(_Tp) type;
-    };
+    : public __underlying_type_impl<_Tp>
+    { };
 
   template<typename _Tp>
     struct __declval_protector
diff --git a/libstdc++-v3/testsuite/20_util/underlying_type/requirements/typedefs-3.cc b/libstdc++-v3/testsuite/20_util/underlying_type/requirements/typedefs-3.cc
new file mode 100644
index 00000000000..5b9a4afb093
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/underlying_type/requirements/typedefs-3.cc
@@ -0,0 +1,52 @@ 
+// Copyright (C) 2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-do compile { target c++11 } }
+
+#include <type_traits>
+
+// Test for SFINAE-friendly underlying_type
+
+template<typename T, typename = typename std::underlying_type<T>::type>
+  constexpr bool is_enum(int) { return true; }
+
+template<typename T>
+  constexpr bool is_enum(...) { return false; }
+
+void
+test01()
+{
+  enum E { };
+  static_assert( is_enum<E>(0), "");
+
+  static_assert( !is_enum<void>(0), "");
+  static_assert( !is_enum<int>(0), "");
+  static_assert( !is_enum<long>(0), "");
+  static_assert( !is_enum<int*>(0), "");
+  static_assert( !is_enum<int[]>(0), "");
+  static_assert( !is_enum<const int*>(0), "");
+  static_assert( !is_enum<const int&>(0), "");
+  static_assert( !is_enum<int()>(0), "");
+  static_assert( !is_enum<int(&)()>(0), "");
+  static_assert( !is_enum<int(*)()>(0), "");
+  struct S { };
+  static_assert( !is_enum<S>(0), "");
+  static_assert( !is_enum<S&>(0), "");
+  static_assert( !is_enum<S*>(0), "");
+  static_assert( !is_enum<int S::*>(0), "");
+  static_assert( !is_enum<int (S::*)()>(0), "");
+}