forked from OSchip/llvm-project
[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
This commit is contained in:
parent
9667d15e74
commit
1f1250151f
|
@ -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","",""
|
||||
"","","","","",""
|
||||
|
|
|
|
@ -292,7 +292,7 @@ Status
|
|||
------------------------------------------------- -----------------
|
||||
**C++ 2b**
|
||||
-------------------------------------------------------------------
|
||||
``__cpp_lib_is_scoped_enum`` *unimplemented*
|
||||
``__cpp_lib_is_scoped_enum`` ``202011L``
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_stacktrace`` *unimplemented*
|
||||
------------------------------------------------- -----------------
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -368,7 +368,6 @@ feature_test_macros = [ add_version_header(x) for x in [
|
|||
"name": "__cpp_lib_is_scoped_enum",
|
||||
"values": { "c++2b": 202011 },
|
||||
"headers": ["type_traits"],
|
||||
"unimplemented": True,
|
||||
}, {
|
||||
"name": "__cpp_lib_is_swappable",
|
||||
"values": { "c++17": 201603 },
|
||||
|
|
Loading…
Reference in New Issue