[libcxx-commits] [PATCH] D63574: Implement P0340R3: Make `underlying_type` SFINAE-friendly
Marshall Clow via Phabricator via libcxx-commits
libcxx-commits at lists.llvm.org
Wed Jun 19 14:27:39 PDT 2019
mclow.lists created this revision.
mclow.lists added reviewers: rsmith, EricWF, ldionne, zoecarver.
Herald added subscribers: dexonsmith, christof.
https://wg21.link/P0340R3
There are two possible approaches here:
- A library-only solution (this patch)
- Some compiler work (updating the `__underlying_type` intrinsic)
After working on this for a bit, I think this is the better approach.
Repository:
rCXX libc++
https://reviews.llvm.org/D63574
Files:
libcxx/include/type_traits
libcxx/test/std/utilities/meta/meta.trans/meta.trans.other/underlying_type.fail.cpp
libcxx/test/std/utilities/meta/meta.trans/meta.trans.other/underlying_type.pass.cpp
Index: libcxx/test/std/utilities/meta/meta.trans/meta.trans.other/underlying_type.pass.cpp
===================================================================
--- libcxx/test/std/utilities/meta/meta.trans/meta.trans.other/underlying_type.pass.cpp
+++ libcxx/test/std/utilities/meta/meta.trans/meta.trans.other/underlying_type.pass.cpp
@@ -15,6 +15,18 @@
#include "test_macros.h"
+#if TEST_STD_VER > 17
+template <class, class = std::void_t<>>
+struct has_type_member : std::false_type {};
+
+template <class T>
+struct has_type_member<T,
+ std::void_t<typename std::underlying_type<T>::type>> : std::true_type {};
+
+struct S {};
+#endif
+
+
enum E { V = INT_MIN };
#if !defined(_WIN32) || defined(__MINGW32__)
@@ -50,5 +62,18 @@
#endif // TEST_STD_VER > 11
#endif // TEST_STD_VER >= 11
+#if TEST_STD_VER > 17
+ static_assert( has_type_member<E>::value, "");
+ static_assert( has_type_member<F>::value, "");
+ static_assert( has_type_member<G>::value, "");
+
+ static_assert(!has_type_member<void>::value, "");
+ static_assert(!has_type_member<int>::value, "");
+ static_assert(!has_type_member<int[]>::value, "");
+ static_assert(!has_type_member<S>::value, "");
+ static_assert(!has_type_member<decltype(main)>::value, "");
+ static_assert(!has_type_member<int&>::value, "");
+#endif
+
return 0;
}
Index: libcxx/test/std/utilities/meta/meta.trans/meta.trans.other/underlying_type.fail.cpp
===================================================================
--- /dev/null
+++ libcxx/test/std/utilities/meta/meta.trans/meta.trans.other/underlying_type.fail.cpp
@@ -0,0 +1,24 @@
+//===----------------------------------------------------------------------===//
+//
+// 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++98, c++03, c++11, C++14, c++17
+// type_traits
+
+// underlying_type
+// Mandates: enum must not be an incomplete enumeration type.
+
+#include <type_traits>
+#include <climits>
+
+#include "test_macros.h"
+
+enum E1 { zero, one, two = sizeof(std::underlying_type<E1>::type) };
+
+int main(int, char**)
+{
+ return 0;
+}
Index: libcxx/include/type_traits
===================================================================
--- libcxx/include/type_traits
+++ libcxx/include/type_traits
@@ -4726,8 +4726,14 @@
#ifdef _LIBCPP_UNDERLYING_TYPE
+template <class _Tp, bool = is_enum<_Tp>::value> struct underlying_type;
+
+
template <class _Tp>
-struct underlying_type
+struct underlying_type<_Tp, false> {};
+
+template <class _Tp>
+struct underlying_type<_Tp, true>
{
typedef _LIBCPP_UNDERLYING_TYPE(_Tp) type;
};
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D63574.205672.patch
Type: text/x-patch
Size: 2824 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/libcxx-commits/attachments/20190619/bf38feb7/attachment.bin>
More information about the libcxx-commits
mailing list