"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","",""
"","","","","",""
------------------------------------------------- -----------------
**C++ 2b**
-------------------------------------------------------------------
- ``__cpp_lib_is_scoped_enum`` *unimplemented*
+ ``__cpp_lib_is_scoped_enum`` ``202011L``
------------------------------------------------- -----------------
``__cpp_lib_stacktrace`` *unimplemented*
------------------------------------------------- -----------------
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;
= 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
#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>
#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
# 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
# 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
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// 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;
+}
"name": "__cpp_lib_is_scoped_enum",
"values": { "c++2b": 202011 },
"headers": ["type_traits"],
- "unimplemented": True,
}, {
"name": "__cpp_lib_is_swappable",
"values": { "c++17": 201603 },