P0340R2 Making std::underlying_type SFINAE-friendly
authorJonathan Wakely <jwakely@redhat.com>
Sat, 23 Feb 2019 21:19:00 +0000 (21:19 +0000)
committerJonathan Wakely <redi@gcc.gnu.org>
Sat, 23 Feb 2019 21:19:00 +0000 (21:19 +0000)
* 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.

From-SVN: r269168

libstdc++-v3/ChangeLog
libstdc++-v3/include/std/type_traits
libstdc++-v3/testsuite/20_util/underlying_type/requirements/typedefs-3.cc [new file with mode: 0644]

index 4596af8260914132ea8c1f76115737d36e959e2c..0b6b05063d767fc90a993523d45b753e5e2535c3 100644 (file)
@@ -1,5 +1,11 @@
 2019-02-23  Jonathan Wakely  <jwakely@redhat.com>
 
+       * 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.
+
        PR libstdc++/89446
        * include/bits/char_traits.h (__constant_char_array): Check index is
        in range before dereferencing.
index 993967244ffbcceac6644d1c19244100fcafd55a..977ca0e1350c64f6d966f3e7d61c6a900dda5ece 100644 (file)
@@ -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 (file)
index 0000000..5b9a4af
--- /dev/null
@@ -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), "");
+}