diff options
author | Marek Kurdej <marek.kurdej@gmail.com> | 2021-01-12 17:06:58 +0100 |
---|---|---|
committer | Marek Kurdej <marek.kurdej@gmail.com> | 2021-01-12 17:08:20 +0100 |
commit | 1f1250151f222ba391d05dcc173f4b6c65d05ca2 (patch) | |
tree | 58fce1ccbcd14693bad4cc31d5671115ddcf2949 | |
parent | 9667d15e7496e6d8c313251f22ac157dbbd0c1c2 (diff) | |
download | llvm-1f1250151f222ba391d05dcc173f4b6c65d05ca2.zip llvm-1f1250151f222ba391d05dcc173f4b6c65d05ca2.tar.gz llvm-1f1250151f222ba391d05dcc173f4b6c65d05ca2.tar.bz2 |
[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
8 files changed, 155 insertions, 26 deletions
diff --git a/libcxx/docs/Cxx2bStatusPaperStatus.csv b/libcxx/docs/Cxx2bStatusPaperStatus.csv index c795095..f5c893f 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 99fb4e7..8221bbe 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 99b2a8f..48884ea 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 3920b69..9e5fc81 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 04c6aaa..41bc22f 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 664c8fe..3ff920c 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 0000000..ad50755 --- /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 daa40f2..c08771f 100755 --- a/libcxx/utils/generate_feature_test_macro_components.py +++ b/libcxx/utils/generate_feature_test_macro_components.py @@ -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 }, |