diff --git a/include/bit.h b/include/bit.h index 992ecbb..d50ec7d 100644 --- a/include/bit.h +++ b/include/bit.h @@ -7,8 +7,6 @@ namespace dark { -static constexpr std::size_t kMaxLength = std::numeric_limits::digits; - template struct Bit { private: @@ -31,10 +29,10 @@ struct Bit { requires ((_Tp::_Bit_Len + ...) == _Nm) constexpr Bit(const _Tp &...args); - template _Tp> + template _Tp> constexpr Bit &operator=(const _Tp &val); - template _Tp> + template _Tp> constexpr void set(const _Tp &val); template diff --git a/include/bit_impl.h b/include/bit_impl.h index a62f15d..e67ec17 100644 --- a/include/bit_impl.h +++ b/include/bit_impl.h @@ -42,7 +42,7 @@ constexpr Bit<_Nm>::Bit(const _Tp &...args) : _M_data(int_concat<_Tp::_Bit_Len...>(static_cast(args)...)) {} template -template > _Tp> +template _Tp> constexpr Bit<_Nm> &Bit<_Nm>::operator=(const _Tp &val) { this->_M_data = static_cast(val); return *this; @@ -56,17 +56,13 @@ constexpr void Bit<_Nm>::_M_range_check() { } template -template > _Tp> +template _Tp> constexpr void Bit<_Nm>::set(const _Tp &val) { this->_M_range_check<_Hi, _Lo>(); auto data = static_cast(val); constexpr auto _Length = _Hi - _Lo + 1; - if constexpr (_Length == kMaxLength) { - this->_M_data = data; - } else { - auto mask = ((1 << _Length) - 1) << _Lo; - this->_M_data = (this->_M_data & ~mask) | ((data << _Lo) & mask); - } + auto mask = make_mask<_Length> << _Lo; + this->_M_data = (this->_M_data & ~mask) | ((data << _Lo) & mask); } template @@ -82,11 +78,7 @@ template constexpr auto Bit<_Nm>::slice(std::size_t pos) const -> Bit <_Len> { static_assert(_Len <= _Nm, "Bit::slice: _Len should be no greater than _Nm"); debug::assert(pos <= _Nm - _Len, "Bit::slice: pos should be less than _Nm - _Len"); - if constexpr (_Len == kMaxLength) { - return *this; - } else { - return Bit<_Len>(this->_M_data >> pos); - } + return Bit<_Len>(this->_M_data >> pos); } diff --git a/include/concept.h b/include/concept.h index 6d47846..905e98c 100644 --- a/include/concept.h +++ b/include/concept.h @@ -7,6 +7,14 @@ namespace dark { using max_size_t = std::uint32_t; using max_ssize_t = std::int32_t; +static constexpr std::size_t kMaxLength = std::numeric_limits::digits; + +template +consteval max_size_t make_mask() { + static_assert(_Len <= kMaxLength, "Mask length out of range"); + return _Len == kMaxLength ? ~max_size_t(0) : (max_size_t(1) << _Len) - 1; +} + } // namespace dark namespace dark::concepts { @@ -38,4 +46,8 @@ concept bit_match = (bit_type <_Lhs> && bit_type <_Rhs> && _Lhs::_Bit_Len == _Rhs::_Bit_Len) || (int_type <_Lhs> || int_type <_Rhs>); +template +concept bit_convertible = + (bit_type <_Tp> && _Tp::_Bit_Len == _Len) || int_type <_Tp>; + } // namespace dark::concepts