[llvm-branch-commits] [libcxx] 1f12501 - [libc++] [C++2b] [P1048] Add is_scoped_enum and is_scoped_enum_v.

Marek Kurdej via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Tue Jan 12 08:12:46 PST 2021


Author: Marek Kurdej
Date: 2021-01-12T17:08:20+01:00
New Revision: 1f1250151f222ba391d05dcc173f4b6c65d05ca2

URL: https://github.com/llvm/llvm-project/commit/1f1250151f222ba391d05dcc173f4b6c65d05ca2
DIFF: https://github.com/llvm/llvm-project/commit/1f1250151f222ba391d05dcc173f4b6c65d05ca2.diff

LOG: [libc++] [C++2b] [P1048] Add is_scoped_enum and is_scoped_enum_v.

* https://wg21.link/p1048

Reviewed By: ldionne, #libc

Differential Revision: https://reviews.llvm.org/D94409

Added: 
    libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_scoped_enum.pass.cpp

Modified: 
    libcxx/docs/Cxx2bStatusPaperStatus.csv
    libcxx/docs/FeatureTestMacroTable.rst
    libcxx/include/type_traits
    libcxx/include/version
    libcxx/test/std/language.support/support.limits/support.limits.general/type_traits.version.pass.cpp
    libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp
    libcxx/utils/generate_feature_test_macro_components.py

Removed: 
    


################################################################################
diff  --git a/libcxx/docs/Cxx2bStatusPaperStatus.csv b/libcxx/docs/Cxx2bStatusPaperStatus.csv
index c79509528add..f5c893fdbd48 100644
--- a/libcxx/docs/Cxx2bStatusPaperStatus.csv
+++ b/libcxx/docs/Cxx2bStatusPaperStatus.csv
@@ -1,6 +1,6 @@
 "Paper #","Group","Paper Name","Meeting","Status","First released version"
 "`P0881R7 <https://wg21.link/P0881R7>`__","LWG","A Proposal to add stacktrace library","Autumn 2020","",""
 "`P0943R6 <https://wg21.link/P0943R6>`__","LWG","Support C atomics in C++","Autumn 2020","",""
-"`P1048R1 <https://wg21.link/P1048R1>`__","LWG","A proposal for a type trait to detect scoped enumerations","Autumn 2020","",""
+"`P1048R1 <https://wg21.link/P1048R1>`__","LWG","A proposal for a type trait to detect scoped enumerations","Autumn 2020","|Complete|","12.0"
 "`P1679R3 <https://wg21.link/P1679R3>`__","LWG","string contains function","Autumn 2020","",""
 "","","","","",""

diff  --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst
index 99fb4e790c7d..8221bbe2a4af 100644
--- a/libcxx/docs/FeatureTestMacroTable.rst
+++ b/libcxx/docs/FeatureTestMacroTable.rst
@@ -292,7 +292,7 @@ Status
     ------------------------------------------------- -----------------
     **C++ 2b**
     -------------------------------------------------------------------
-    ``__cpp_lib_is_scoped_enum``                      *unimplemented*
+    ``__cpp_lib_is_scoped_enum``                      ``202011L``
     ------------------------------------------------- -----------------
     ``__cpp_lib_stacktrace``                          *unimplemented*
     ------------------------------------------------- -----------------

diff  --git a/libcxx/include/type_traits b/libcxx/include/type_traits
index 99b2a8f9f025..48884eab8e86 100644
--- a/libcxx/include/type_traits
+++ b/libcxx/include/type_traits
@@ -51,6 +51,7 @@ namespace std
     template <class T> struct is_arithmetic;
     template <class T> struct is_fundamental;
     template <class T> struct is_member_pointer;
+    template <class T> struct is_scoped_enum; // C++2b
     template <class T> struct is_scalar;
     template <class T> struct is_object;
     template <class T> struct is_compound;
@@ -284,6 +285,8 @@ namespace std
         = is_compound<T>::value;                                         // C++17
       template <class T> inline constexpr bool is_member_pointer_v
         = is_member_pointer<T>::value;                                   // C++17
+      template <class T> inline constexpr bool is_scoped_enum_v
+        = is_scoped_enum<T>::value;                                      // C++2b
 
       // See C++14 20.10.4.3, type properties
       template <class T> inline constexpr bool is_const_v
@@ -4177,6 +4180,25 @@ struct __has_operator_addressof
 
 #endif  // _LIBCPP_CXX03_LANG
 
+// is_scoped_enum [meta.unary.prop]
+
+#if _LIBCPP_STD_VER > 20
+template <class _Tp, bool = is_enum_v<_Tp> >
+struct __is_scoped_enum_helper : false_type {};
+
+template <class _Tp>
+struct __is_scoped_enum_helper<_Tp, true>
+    : public bool_constant<!is_convertible_v<_Tp, underlying_type_t<_Tp> > > {};
+
+template <class _Tp>
+struct _LIBCPP_TEMPLATE_VIS is_scoped_enum
+    : public __is_scoped_enum_helper<_Tp> {};
+
+template <class _Tp>
+_LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_scoped_enum_v =
+    is_scoped_enum<_Tp>::value;
+#endif
+
 #if _LIBCPP_STD_VER > 14
 
 template <class... _Args>

diff  --git a/libcxx/include/version b/libcxx/include/version
index 3920b69a601c..9e5fc81da44e 100644
--- a/libcxx/include/version
+++ b/libcxx/include/version
@@ -355,7 +355,7 @@ __cpp_lib_void_t                                        201411L <type_traits>
 #endif
 
 #if _LIBCPP_STD_VER > 20
-// # define __cpp_lib_is_scoped_enum                       202011L
+# define __cpp_lib_is_scoped_enum                       202011L
 // # define __cpp_lib_stacktrace                           202011L
 // # define __cpp_lib_stdatomic_h                          202011L
 // # define __cpp_lib_string_contains                      202011L

diff  --git a/libcxx/test/std/language.support/support.limits/support.limits.general/type_traits.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/type_traits.version.pass.cpp
index 04c6aaa81fd7..41bc22f6a330 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/type_traits.version.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/type_traits.version.pass.cpp
@@ -638,17 +638,11 @@
 #   endif
 # endif
 
-# if !defined(_LIBCPP_VERSION)
-#   ifndef __cpp_lib_is_scoped_enum
-#     error "__cpp_lib_is_scoped_enum should be defined in c++2b"
-#   endif
-#   if __cpp_lib_is_scoped_enum != 202011L
-#     error "__cpp_lib_is_scoped_enum should have the value 202011L in c++2b"
-#   endif
-# else // _LIBCPP_VERSION
-#   ifdef __cpp_lib_is_scoped_enum
-#     error "__cpp_lib_is_scoped_enum should not be defined because it is unimplemented in libc++!"
-#   endif
+#ifndef __cpp_lib_is_scoped_enum
+#error "__cpp_lib_is_scoped_enum should be defined in c++2b"
+#endif
+#if __cpp_lib_is_scoped_enum != 202011L
+#error "__cpp_lib_is_scoped_enum should have the value 202011L in c++2b"
 # endif
 
 # ifndef __cpp_lib_is_swappable

diff  --git a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp
index 664c8fe75839..3ff920c3a489 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp
@@ -3983,17 +3983,11 @@
 #   endif
 # endif
 
-# if !defined(_LIBCPP_VERSION)
-#   ifndef __cpp_lib_is_scoped_enum
-#     error "__cpp_lib_is_scoped_enum should be defined in c++2b"
-#   endif
-#   if __cpp_lib_is_scoped_enum != 202011L
-#     error "__cpp_lib_is_scoped_enum should have the value 202011L in c++2b"
-#   endif
-# else // _LIBCPP_VERSION
-#   ifdef __cpp_lib_is_scoped_enum
-#     error "__cpp_lib_is_scoped_enum should not be defined because it is unimplemented in libc++!"
-#   endif
+#ifndef __cpp_lib_is_scoped_enum
+#error "__cpp_lib_is_scoped_enum should be defined in c++2b"
+#endif
+#if __cpp_lib_is_scoped_enum != 202011L
+#error "__cpp_lib_is_scoped_enum should have the value 202011L in c++2b"
 # endif
 
 # ifndef __cpp_lib_is_swappable

diff  --git a/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_scoped_enum.pass.cpp b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_scoped_enum.pass.cpp
new file mode 100644
index 000000000000..ad50755a00cd
--- /dev/null
+++ b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_scoped_enum.pass.cpp
@@ -0,0 +1,120 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++2a
+
+// type_traits
+
+// is_scoped_enum // C++2b
+
+#include <type_traits>
+#include <cstddef> // for std::nullptr_t
+#include "test_macros.h"
+
+template <class T>
+void test_positive() {
+  static_assert(std::is_scoped_enum<T>::value);
+  static_assert(std::is_scoped_enum<const T>::value);
+  static_assert(std::is_scoped_enum<volatile T>::value);
+  static_assert(std::is_scoped_enum<const volatile T>::value);
+
+  static_assert(std::is_scoped_enum_v<T>);
+  static_assert(std::is_scoped_enum_v<const T>);
+  static_assert(std::is_scoped_enum_v<volatile T>);
+  static_assert(std::is_scoped_enum_v<const volatile T>);
+}
+
+template <class T>
+void test_negative() {
+  static_assert(!std::is_scoped_enum<T>::value);
+  static_assert(!std::is_scoped_enum<const T>::value);
+  static_assert(!std::is_scoped_enum<volatile T>::value);
+  static_assert(!std::is_scoped_enum<const volatile T>::value);
+
+  static_assert(!std::is_scoped_enum_v<T>);
+  static_assert(!std::is_scoped_enum_v<const T>);
+  static_assert(!std::is_scoped_enum_v<volatile T>);
+  static_assert(!std::is_scoped_enum_v<const volatile T>);
+}
+
+class Empty {};
+
+class NotEmpty {
+  virtual ~NotEmpty();
+};
+
+union Union {};
+
+struct bit_zero {
+  int : 0;
+};
+
+class Abstract {
+  virtual ~Abstract() = 0;
+};
+
+enum Enum { zero, one };
+enum class CEnum1 { zero, one };
+enum class CEnum2;
+enum class CEnum3 : short;
+struct incomplete_type;
+
+using FunctionPtr = void (*)();
+using FunctionType = void();
+
+struct TestMembers {
+  static int static_method(int) { return 0; }
+  int method() { return 0; }
+
+  enum E1 { m_zero, m_one };
+  enum class CE1;
+};
+
+void func1();
+int func2(int);
+
+int main(int, char**) {
+  test_positive<CEnum1>();
+  test_positive<CEnum2>();
+  test_positive<CEnum3>();
+  test_positive<TestMembers::CE1>();
+
+  test_negative<Enum>();
+  test_negative<TestMembers::E1>();
+
+  test_negative<std::nullptr_t>();
+  test_negative<void>();
+  test_negative<int>();
+  test_negative<int&>();
+  test_negative<int&&>();
+  test_negative<int*>();
+  test_negative<double>();
+  test_negative<const int*>();
+  test_negative<char[3]>();
+  test_negative<char[]>();
+  test_negative<Union>();
+  test_negative<Empty>();
+  test_negative<bit_zero>();
+  test_negative<NotEmpty>();
+  test_negative<Abstract>();
+  test_negative<FunctionPtr>();
+  test_negative<FunctionType>();
+  test_negative<incomplete_type>();
+  test_negative<int TestMembers::*>();
+  test_negative<void (TestMembers::*)()>();
+
+  test_negative<decltype(func1)>();
+  test_negative<decltype(&func1)>();
+  test_negative<decltype(func2)>();
+  test_negative<decltype(&func2)>();
+  test_negative<decltype(TestMembers::static_method)>();
+  test_negative<decltype(&TestMembers::static_method)>();
+  test_negative<decltype(&TestMembers::method)>();
+
+  return 0;
+}

diff  --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py
index daa40f2a15ac..c08771fc056c 100755
--- a/libcxx/utils/generate_feature_test_macro_components.py
+++ b/libcxx/utils/generate_feature_test_macro_components.py
@@ -368,7 +368,6 @@ def add_version_header(tc):
     "name": "__cpp_lib_is_scoped_enum",
     "values": { "c++2b": 202011 },
     "headers": ["type_traits"],
-    "unimplemented": True,
   }, {
     "name": "__cpp_lib_is_swappable",
     "values": { "c++17": 201603 },


        


More information about the llvm-branch-commits mailing list