Skip to content

Commit 1f12501

Browse files
committed
[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
1 parent 9667d15 commit 1f12501

File tree

8 files changed

+155
-26
lines changed

8 files changed

+155
-26
lines changed
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"Paper #","Group","Paper Name","Meeting","Status","First released version"
22
"`P0881R7 <https://wg21.link/P0881R7>`__","LWG","A Proposal to add stacktrace library","Autumn 2020","",""
33
"`P0943R6 <https://wg21.link/P0943R6>`__","LWG","Support C atomics in C++","Autumn 2020","",""
4-
"`P1048R1 <https://wg21.link/P1048R1>`__","LWG","A proposal for a type trait to detect scoped enumerations","Autumn 2020","",""
4+
"`P1048R1 <https://wg21.link/P1048R1>`__","LWG","A proposal for a type trait to detect scoped enumerations","Autumn 2020","|Complete|","12.0"
55
"`P1679R3 <https://wg21.link/P1679R3>`__","LWG","string contains function","Autumn 2020","",""
66
"","","","","",""

libcxx/docs/FeatureTestMacroTable.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,7 @@ Status
292292
------------------------------------------------- -----------------
293293
**C++ 2b**
294294
-------------------------------------------------------------------
295-
``__cpp_lib_is_scoped_enum`` *unimplemented*
295+
``__cpp_lib_is_scoped_enum`` ``202011L``
296296
------------------------------------------------- -----------------
297297
``__cpp_lib_stacktrace`` *unimplemented*
298298
------------------------------------------------- -----------------

libcxx/include/type_traits

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ namespace std
5151
template <class T> struct is_arithmetic;
5252
template <class T> struct is_fundamental;
5353
template <class T> struct is_member_pointer;
54+
template <class T> struct is_scoped_enum; // C++2b
5455
template <class T> struct is_scalar;
5556
template <class T> struct is_object;
5657
template <class T> struct is_compound;
@@ -284,6 +285,8 @@ namespace std
284285
= is_compound<T>::value; // C++17
285286
template <class T> inline constexpr bool is_member_pointer_v
286287
= is_member_pointer<T>::value; // C++17
288+
template <class T> inline constexpr bool is_scoped_enum_v
289+
= is_scoped_enum<T>::value; // C++2b
287290
288291
// See C++14 20.10.4.3, type properties
289292
template <class T> inline constexpr bool is_const_v
@@ -4177,6 +4180,25 @@ struct __has_operator_addressof
41774180

41784181
#endif // _LIBCPP_CXX03_LANG
41794182

4183+
// is_scoped_enum [meta.unary.prop]
4184+
4185+
#if _LIBCPP_STD_VER > 20
4186+
template <class _Tp, bool = is_enum_v<_Tp> >
4187+
struct __is_scoped_enum_helper : false_type {};
4188+
4189+
template <class _Tp>
4190+
struct __is_scoped_enum_helper<_Tp, true>
4191+
: public bool_constant<!is_convertible_v<_Tp, underlying_type_t<_Tp> > > {};
4192+
4193+
template <class _Tp>
4194+
struct _LIBCPP_TEMPLATE_VIS is_scoped_enum
4195+
: public __is_scoped_enum_helper<_Tp> {};
4196+
4197+
template <class _Tp>
4198+
_LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_scoped_enum_v =
4199+
is_scoped_enum<_Tp>::value;
4200+
#endif
4201+
41804202
#if _LIBCPP_STD_VER > 14
41814203

41824204
template <class... _Args>

libcxx/include/version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -355,7 +355,7 @@ __cpp_lib_void_t 201411L <type_traits>
355355
#endif
356356

357357
#if _LIBCPP_STD_VER > 20
358-
// # define __cpp_lib_is_scoped_enum 202011L
358+
# define __cpp_lib_is_scoped_enum 202011L
359359
// # define __cpp_lib_stacktrace 202011L
360360
// # define __cpp_lib_stdatomic_h 202011L
361361
// # define __cpp_lib_string_contains 202011L

libcxx/test/std/language.support/support.limits/support.limits.general/type_traits.version.pass.cpp

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -638,17 +638,11 @@
638638
# endif
639639
# endif
640640

641-
# if !defined(_LIBCPP_VERSION)
642-
# ifndef __cpp_lib_is_scoped_enum
643-
# error "__cpp_lib_is_scoped_enum should be defined in c++2b"
644-
# endif
645-
# if __cpp_lib_is_scoped_enum != 202011L
646-
# error "__cpp_lib_is_scoped_enum should have the value 202011L in c++2b"
647-
# endif
648-
# else // _LIBCPP_VERSION
649-
# ifdef __cpp_lib_is_scoped_enum
650-
# error "__cpp_lib_is_scoped_enum should not be defined because it is unimplemented in libc++!"
651-
# endif
641+
#ifndef __cpp_lib_is_scoped_enum
642+
#error "__cpp_lib_is_scoped_enum should be defined in c++2b"
643+
#endif
644+
#if __cpp_lib_is_scoped_enum != 202011L
645+
#error "__cpp_lib_is_scoped_enum should have the value 202011L in c++2b"
652646
# endif
653647

654648
# ifndef __cpp_lib_is_swappable

libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3983,17 +3983,11 @@
39833983
# endif
39843984
# endif
39853985

3986-
# if !defined(_LIBCPP_VERSION)
3987-
# ifndef __cpp_lib_is_scoped_enum
3988-
# error "__cpp_lib_is_scoped_enum should be defined in c++2b"
3989-
# endif
3990-
# if __cpp_lib_is_scoped_enum != 202011L
3991-
# error "__cpp_lib_is_scoped_enum should have the value 202011L in c++2b"
3992-
# endif
3993-
# else // _LIBCPP_VERSION
3994-
# ifdef __cpp_lib_is_scoped_enum
3995-
# error "__cpp_lib_is_scoped_enum should not be defined because it is unimplemented in libc++!"
3996-
# endif
3986+
#ifndef __cpp_lib_is_scoped_enum
3987+
#error "__cpp_lib_is_scoped_enum should be defined in c++2b"
3988+
#endif
3989+
#if __cpp_lib_is_scoped_enum != 202011L
3990+
#error "__cpp_lib_is_scoped_enum should have the value 202011L in c++2b"
39973991
# endif
39983992

39993993
# ifndef __cpp_lib_is_swappable
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++2a
10+
11+
// type_traits
12+
13+
// is_scoped_enum // C++2b
14+
15+
#include <type_traits>
16+
#include <cstddef> // for std::nullptr_t
17+
#include "test_macros.h"
18+
19+
template <class T>
20+
void test_positive() {
21+
static_assert(std::is_scoped_enum<T>::value);
22+
static_assert(std::is_scoped_enum<const T>::value);
23+
static_assert(std::is_scoped_enum<volatile T>::value);
24+
static_assert(std::is_scoped_enum<const volatile T>::value);
25+
26+
static_assert(std::is_scoped_enum_v<T>);
27+
static_assert(std::is_scoped_enum_v<const T>);
28+
static_assert(std::is_scoped_enum_v<volatile T>);
29+
static_assert(std::is_scoped_enum_v<const volatile T>);
30+
}
31+
32+
template <class T>
33+
void test_negative() {
34+
static_assert(!std::is_scoped_enum<T>::value);
35+
static_assert(!std::is_scoped_enum<const T>::value);
36+
static_assert(!std::is_scoped_enum<volatile T>::value);
37+
static_assert(!std::is_scoped_enum<const volatile T>::value);
38+
39+
static_assert(!std::is_scoped_enum_v<T>);
40+
static_assert(!std::is_scoped_enum_v<const T>);
41+
static_assert(!std::is_scoped_enum_v<volatile T>);
42+
static_assert(!std::is_scoped_enum_v<const volatile T>);
43+
}
44+
45+
class Empty {};
46+
47+
class NotEmpty {
48+
virtual ~NotEmpty();
49+
};
50+
51+
union Union {};
52+
53+
struct bit_zero {
54+
int : 0;
55+
};
56+
57+
class Abstract {
58+
virtual ~Abstract() = 0;
59+
};
60+
61+
enum Enum { zero, one };
62+
enum class CEnum1 { zero, one };
63+
enum class CEnum2;
64+
enum class CEnum3 : short;
65+
struct incomplete_type;
66+
67+
using FunctionPtr = void (*)();
68+
using FunctionType = void();
69+
70+
struct TestMembers {
71+
static int static_method(int) { return 0; }
72+
int method() { return 0; }
73+
74+
enum E1 { m_zero, m_one };
75+
enum class CE1;
76+
};
77+
78+
void func1();
79+
int func2(int);
80+
81+
int main(int, char**) {
82+
test_positive<CEnum1>();
83+
test_positive<CEnum2>();
84+
test_positive<CEnum3>();
85+
test_positive<TestMembers::CE1>();
86+
87+
test_negative<Enum>();
88+
test_negative<TestMembers::E1>();
89+
90+
test_negative<std::nullptr_t>();
91+
test_negative<void>();
92+
test_negative<int>();
93+
test_negative<int&>();
94+
test_negative<int&&>();
95+
test_negative<int*>();
96+
test_negative<double>();
97+
test_negative<const int*>();
98+
test_negative<char[3]>();
99+
test_negative<char[]>();
100+
test_negative<Union>();
101+
test_negative<Empty>();
102+
test_negative<bit_zero>();
103+
test_negative<NotEmpty>();
104+
test_negative<Abstract>();
105+
test_negative<FunctionPtr>();
106+
test_negative<FunctionType>();
107+
test_negative<incomplete_type>();
108+
test_negative<int TestMembers::*>();
109+
test_negative<void (TestMembers::*)()>();
110+
111+
test_negative<decltype(func1)>();
112+
test_negative<decltype(&func1)>();
113+
test_negative<decltype(func2)>();
114+
test_negative<decltype(&func2)>();
115+
test_negative<decltype(TestMembers::static_method)>();
116+
test_negative<decltype(&TestMembers::static_method)>();
117+
test_negative<decltype(&TestMembers::method)>();
118+
119+
return 0;
120+
}

libcxx/utils/generate_feature_test_macro_components.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -368,7 +368,6 @@ def add_version_header(tc):
368368
"name": "__cpp_lib_is_scoped_enum",
369369
"values": { "c++2b": 202011 },
370370
"headers": ["type_traits"],
371-
"unimplemented": True,
372371
}, {
373372
"name": "__cpp_lib_is_swappable",
374373
"values": { "c++17": 201603 },

0 commit comments

Comments
 (0)