[libcxx-commits] [libcxx] [libc++] Implement `<bit>` parts of P3793R2 Better shifting (PR #219389)

Jan Schultke via libcxx-commits libcxx-commits at lists.llvm.org
Mon Aug 31 00:21:33 PDT 2026


================
@@ -0,0 +1,275 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++29
+
+// template <class T, class S>
+//   constexpr T shl(T x, S s) noexcept;
+
+// Constraints: Each of T and S is a signed or unsigned integer type.
+
+#include <bit>
+#include <cassert>
+#include <limits>
+#include <type_traits>
+
+#include "test_macros.h"
+#include "type_algorithms.h"
+
+struct A {};
+enum E1 : unsigned char { rEd };
+enum class E2 : unsigned char { red };
+
+template <class T>
+concept can_shl_value = requires(T value) { std::shl(value, 1); };
+
+static_assert(can_shl_value<int>, "Concept is broken. We should be able to shift int.");
+static_assert(!can_shl_value<bool>);
+static_assert(!can_shl_value<char>);
+static_assert(!can_shl_value<wchar_t>);
+static_assert(!can_shl_value<char8_t>);
+static_assert(!can_shl_value<char16_t>);
+static_assert(!can_shl_value<char32_t>);
+static_assert(!can_shl_value<A>);
+static_assert(!can_shl_value<A*>);
+static_assert(!can_shl_value<E1>);
+static_assert(!can_shl_value<E2>);
+
+template <class T>
+concept can_shl_shift = requires(T shift) { std::shl(1, shift); };
+
+static_assert(can_shl_shift<int>, "Concept is broken. We should be able to shift by int.");
+static_assert(!can_shl_shift<bool>);
+static_assert(!can_shl_shift<char>);
+static_assert(!can_shl_shift<wchar_t>);
+static_assert(!can_shl_shift<char8_t>);
+static_assert(!can_shl_shift<char16_t>);
+static_assert(!can_shl_shift<char32_t>);
+static_assert(!can_shl_shift<A>);
+static_assert(!can_shl_shift<A*>);
+static_assert(!can_shl_shift<E1>);
+static_assert(!can_shl_shift<E2>);
+
+template <class T>
+constexpr bool test() {
+  using U               = std::make_unsigned_t<T>;
+  constexpr int width   = std::numeric_limits<U>::digits;
+  constexpr U highbit_u = U(1) << (width - 1);
+
+  if constexpr (std::is_signed_v<T>) {
----------------
eisenwave wrote:

I'm not convinced that the extra level of indent has meaningful impact here.

I'd be fine with the change if there weren't those lines of shared logic for determining the bit-width of the type, and it seems more flexible to have such a shared section.

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


More information about the libcxx-commits mailing list