numeric_shr
numeric_shr (포화 오른쪽 시프트)
std::shr은 ⌊x · 2⁻ˢ⌋를 음의 무한 방향으로 반올림하고 T에 맞게 잘라낸 값을 반환하는 함수예요. C++29부터 사용할 수 있어요.
출처: cppreference
본문
<bit> 헤더에 정의되어 있고, 시그니처는 다음과 같아요.
template< class T, class S >
constexpr T shr( T x, S s ) noexcept;
(since C++29)
⌊x · 2⁻ˢ⌋를 음의 무한 방향으로 반올림하고 T에 맞게 잘라낸 값을 반환해요.
매개변수 (Parameters)
- x — 시프트할 값
- s — 시프트할 위치 수
타입 요구사항 (Type requirements)
- T, S — 오버로드 해석에 참여하려면 부호 또는 무부호 정수 타입이어야 해요.
반환값 (Return value)
결과 타입으로 잘라낸 ⌊x · 2⁻ˢ⌋.
참고 (Notes)
>> 연산자와 달리 std::shr은 절대 정의되지 않은 동작이 없어요.
시프트는 s가 양수이면 한 비트씩 s번 오른쪽으로, s가 음수이면 한 비트씩 -s번 왼쪽으로 시프트하는 것처럼 일어나는데, -s가 오버플로되지 않아야 해요.
| 피처 테스트 매크로 | 값 | 표준 | 기능 |
|---|---|---|---|
__cpp_lib_bitops |
202606L | (C++29) | 더 나은 시프트 |
가능한 구현 (Possible implementation)
template<typename T, typename ... U>
concept neither = (!std::same_as<T, U> && ...);
template<typename T>
concept integer = std::integral<T> and
neither<T, bool, char, char8_t, char16_t, char32_t, wchar_t>;
template<integer T, integer S>
constexpr T shr(T x, S s) noexcept
{
constexpr auto width = S(std::numeric_limits<std::make_unsigned_t<T>>::digits);
if constexpr (std::is_signed_v<S>)
{
if (s < 0)
return s <= -width ? T(0) : x << -s;
}
return s >= width ? T(x < 0 ? -1 : 0) : x >> s;
}
예제 (Example)
이 코드를 실행해 봐요.
#include <bit>
#include <concepts>
#include <cstdint>
#include <limits>
template<std::unsigned_integral T>
constexpr bool is_set(T bits, int bit_num) noexcept
{
#if (__cpp_lib_bitops >= 202606L)
// Never undefined.
return std::shr(bits, bit_num) & 1;
#else
// Requires special cases to guard against overlong
// shifts, otherwise the behavior is undefined.
if (std::numeric_limits<T>::digits < bit_num)
return false;
return (bits >> bit_num) & 1;
#endif
}