[llvm] [STLExtras] Backport std::to_underlying from C++23 (PR #70681)

via llvm-commits llvm-commits at lists.llvm.org
Mon Oct 30 09:17:17 PDT 2023


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-support

Author: Vlad Serebrennikov (Endilll)

<details>
<summary>Changes</summary>

This patch backports a one-liner `std::to_underlying` that came with C++23. This is useful for refactoring unscoped enums into scoped enums, because the latter are not implicitly convertible to integer types.

I followed libc++ implementation, but I consider their testing too heavy for us, so I wrote a simpler set of tests.

---
Full diff: https://github.com/llvm/llvm-project/pull/70681.diff


2 Files Affected:

- (modified) llvm/include/llvm/ADT/STLExtras.h (+6) 
- (modified) llvm/unittests/ADT/STLExtrasTest.cpp (+22) 


``````````diff
diff --git a/llvm/include/llvm/ADT/STLExtras.h b/llvm/include/llvm/ADT/STLExtras.h
index 18bc4d108b156bf..98342bfc36e9f83 100644
--- a/llvm/include/llvm/ADT/STLExtras.h
+++ b/llvm/include/llvm/ADT/STLExtras.h
@@ -1535,6 +1535,12 @@ constexpr decltype(auto) makeVisitor(CallableTs &&...Callables) {
   return detail::Visitor<CallableTs...>(std::forward<CallableTs>(Callables)...);
 }
 
+/// Backport of C++23 std::to_underlying.
+template <typename Enum>
+[[nodiscard]] constexpr typename std::underlying_type_t<Enum> to_underlying(Enum E) {
+  return static_cast<typename std::underlying_type_t<Enum>>(E);
+}
+
 //===----------------------------------------------------------------------===//
 //     Extra additions to <algorithm>
 //===----------------------------------------------------------------------===//
diff --git a/llvm/unittests/ADT/STLExtrasTest.cpp b/llvm/unittests/ADT/STLExtrasTest.cpp
index 7db339e4ef31cdc..213b3e4b3d06fb6 100644
--- a/llvm/unittests/ADT/STLExtrasTest.cpp
+++ b/llvm/unittests/ADT/STLExtrasTest.cpp
@@ -1332,4 +1332,26 @@ struct Bar {};
 static_assert(is_incomplete_v<Foo>, "Foo is incomplete");
 static_assert(!is_incomplete_v<Bar>, "Bar is defined");
 
+TEST(STLExtrasTest, ToUnderlying) {
+  enum E {
+    A1 = 0, B1 = -1
+  };
+  static_assert(to_underlying(A1) == 0);
+  static_assert(to_underlying(B1) == -1);
+
+  enum E2 : unsigned char {
+    A2 = 0, B2
+  };
+  static_assert(std::is_same_v<unsigned char, decltype(to_underlying(A2))>);
+  static_assert(to_underlying(A2) == 0);
+  static_assert(to_underlying(B2) == 1);
+
+  enum class E3 {
+    A3 = -1, B3
+  };
+  static_assert(std::is_same_v<int, decltype(to_underlying(E3::A3))>);
+  static_assert(to_underlying(E3::A3) == -1);
+  static_assert(to_underlying(E3::B3) == 0);
+}
+
 } // namespace

``````````

</details>


https://github.com/llvm/llvm-project/pull/70681


More information about the llvm-commits mailing list