Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement P2417R2 More constexpr bitset #2972

Merged
merged 13 commits into from
Aug 3, 2022
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
121 changes: 76 additions & 45 deletions stl/inc/bitset
Original file line number Diff line number Diff line change
Expand Up @@ -32,41 +32,41 @@ public:
friend bitset<_Bits>;

public:
~reference() noexcept {} // TRANSITION, ABI
_CONSTEXPR23 ~reference() noexcept {} // TRANSITION, ABI
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think these should technically be constexpr always (or I guess _CONSTEXPR20 for constexpr destructors), but since one can't create one of these at constexpr time until 23, I don't think it matters.

No change requested.


reference& operator=(bool _Val) noexcept {
_CONSTEXPR23 reference& operator=(bool _Val) noexcept {
fsb4000 marked this conversation as resolved.
Show resolved Hide resolved
_Pbitset->_Set_unchecked(_Mypos, _Val);
return *this;
}

reference& operator=(const reference& _Bitref) noexcept {
_CONSTEXPR23 reference& operator=(const reference& _Bitref) noexcept {
_Pbitset->_Set_unchecked(_Mypos, static_cast<bool>(_Bitref));
return *this;
}

reference& flip() noexcept {
_CONSTEXPR23 reference& flip() noexcept {
_Pbitset->_Flip_unchecked(_Mypos);
return *this;
}

_NODISCARD bool operator~() const noexcept {
_NODISCARD _CONSTEXPR23 bool operator~() const noexcept {
return !_Pbitset->_Subscript(_Mypos);
}

operator bool() const noexcept {
_CONSTEXPR23 operator bool() const noexcept {
return _Pbitset->_Subscript(_Mypos);
}

private:
reference() noexcept : _Pbitset(nullptr), _Mypos(0) {}
_CONSTEXPR23 reference() noexcept : _Pbitset(nullptr), _Mypos(0) {}

reference(bitset<_Bits>& _Bitset, size_t _Pos) : _Pbitset(&_Bitset), _Mypos(_Pos) {}
_CONSTEXPR23 reference(bitset<_Bits>& _Bitset, size_t _Pos) : _Pbitset(&_Bitset), _Mypos(_Pos) {}
fsb4000 marked this conversation as resolved.
Show resolved Hide resolved

bitset<_Bits>* _Pbitset;
size_t _Mypos; // position of element in bitset
};

static void _Validate(size_t _Pos) { // verify that _Pos is within bounds
static _CONSTEXPR23 void _Validate(size_t _Pos) { // verify that _Pos is within bounds
fsb4000 marked this conversation as resolved.
Show resolved Hide resolved
#if _ITERATOR_DEBUG_LEVEL == 0
(void) _Pos;
#else // ^^^ _ITERATOR_DEBUG_LEVEL == 0 ^^^ // vvv _ITERATOR_DEBUG_LEVEL != 0 vvv
Expand All @@ -87,7 +87,7 @@ public:
#endif // _ITERATOR_DEBUG_LEVEL == 0
}

_NODISCARD reference operator[](size_t _Pos) {
_NODISCARD _CONSTEXPR23 reference operator[](size_t _Pos) {
fsb4000 marked this conversation as resolved.
Show resolved Hide resolved
_Validate(_Pos);
return reference(*this, _Pos);
}
Expand All @@ -101,7 +101,7 @@ public:
constexpr bitset(unsigned long long _Val) noexcept : _Array{static_cast<_Ty>(_Need_mask ? _Val & _Mask : _Val)} {}

template <class _Traits, class _Elem>
void _Construct(const _Elem* const _Ptr, size_t _Count, const _Elem _Elem0, const _Elem _Elem1) {
_CONSTEXPR23 void _Construct(const _Elem* const _Ptr, size_t _Count, const _Elem _Elem0, const _Elem _Elem1) {
if (_Count > _Bits) {
for (size_t _Idx = _Bits; _Idx < _Count; ++_Idx) {
const auto _Ch = _Ptr[_Idx];
Expand Down Expand Up @@ -146,7 +146,7 @@ public:
}

template <class _Elem, class _Traits, class _Alloc>
explicit bitset(const basic_string<_Elem, _Traits, _Alloc>& _Str,
_CONSTEXPR23 explicit bitset(const basic_string<_Elem, _Traits, _Alloc>& _Str,
typename basic_string<_Elem, _Traits, _Alloc>::size_type _Pos = 0,
typename basic_string<_Elem, _Traits, _Alloc>::size_type _Count = basic_string<_Elem, _Traits, _Alloc>::npos,
_Elem _Elem0 = static_cast<_Elem>('0'), _Elem _Elem1 = static_cast<_Elem>('1')) {
Expand All @@ -163,7 +163,8 @@ public:
}

template <class _Elem>
explicit bitset(const _Elem* _Ntcts, typename basic_string<_Elem>::size_type _Count = basic_string<_Elem>::npos,
_CONSTEXPR23 explicit bitset(const _Elem* _Ntcts,
typename basic_string<_Elem>::size_type _Count = basic_string<_Elem>::npos,
_Elem _Elem0 = static_cast<_Elem>('0'), _Elem _Elem1 = static_cast<_Elem>('1')) {
if (_Count == basic_string<_Elem>::npos) {
_Count = char_traits<_Elem>::length(_Ntcts);
Expand All @@ -172,31 +173,31 @@ public:
_Construct<char_traits<_Elem>>(_Ntcts, _Count, _Elem0, _Elem1);
}

bitset& operator&=(const bitset& _Right) noexcept {
_CONSTEXPR23 bitset& operator&=(const bitset& _Right) noexcept {
for (size_t _Wpos = 0; _Wpos <= _Words; ++_Wpos) {
_Array[_Wpos] &= _Right._Array[_Wpos];
}

return *this;
}

bitset& operator|=(const bitset& _Right) noexcept {
_CONSTEXPR23 bitset& operator|=(const bitset& _Right) noexcept {
for (size_t _Wpos = 0; _Wpos <= _Words; ++_Wpos) {
_Array[_Wpos] |= _Right._Array[_Wpos];
}

return *this;
}

bitset& operator^=(const bitset& _Right) noexcept {
_CONSTEXPR23 bitset& operator^=(const bitset& _Right) noexcept {
for (size_t _Wpos = 0; _Wpos <= _Words; ++_Wpos) {
_Array[_Wpos] ^= _Right._Array[_Wpos];
}

return *this;
}

bitset& operator<<=(size_t _Pos) noexcept { // shift left by _Pos, first by words then by bits
_CONSTEXPR23 bitset& operator<<=(size_t _Pos) noexcept { // shift left by _Pos, first by words then by bits
const auto _Wordshift = static_cast<ptrdiff_t>(_Pos / _Bitsperword);
if (_Wordshift != 0) {
for (ptrdiff_t _Wpos = _Words; 0 <= _Wpos; --_Wpos) {
Expand All @@ -215,7 +216,7 @@ public:
return *this;
}

bitset& operator>>=(size_t _Pos) noexcept { // shift right by _Pos, first by words then by bits
_CONSTEXPR23 bitset& operator>>=(size_t _Pos) noexcept { // shift right by _Pos, first by words then by bits
const auto _Wordshift = static_cast<ptrdiff_t>(_Pos / _Bitsperword);
if (_Wordshift != 0) {
for (ptrdiff_t _Wpos = 0; _Wpos <= _Words; ++_Wpos) {
Expand All @@ -233,36 +234,54 @@ public:
return *this;
}

bitset& set() noexcept { // set all bits true
_CSTD memset(&_Array, 0xFF, sizeof(_Array));
_CONSTEXPR23 bitset& set() noexcept { // set all bits true
#if _HAS_CXX23
if (_STD is_constant_evaluated()) {
for (auto& _El : _Array) {
_El = 0xFF;
StephanTLavavej marked this conversation as resolved.
Show resolved Hide resolved
}
} else
#endif // _HAS_CXX23
{
_CSTD memset(&_Array, 0xFF, sizeof(_Array));
}
_Trim();
return *this;
}

bitset& set(size_t _Pos, bool _Val = true) { // set bit at _Pos to _Val
_CONSTEXPR23 bitset& set(size_t _Pos, bool _Val = true) { // set bit at _Pos to _Val
fsb4000 marked this conversation as resolved.
Show resolved Hide resolved
if (_Bits <= _Pos) {
_Xran(); // _Pos off end
}

return _Set_unchecked(_Pos, _Val);
}

bitset& reset() noexcept { // set all bits false
_CSTD memset(&_Array, 0, sizeof(_Array));
_CONSTEXPR23 bitset& reset() noexcept { // set all bits false
#if _HAS_CXX23
if (_STD is_constant_evaluated()) {
for (auto& _El : _Array) {
_El = 0;
}
} else
#endif // _HAS_CXX23
{
_CSTD memset(&_Array, 0, sizeof(_Array));
}
return *this;
}

bitset& reset(size_t _Pos) { // set bit at _Pos to false
_CONSTEXPR23 bitset& reset(size_t _Pos) { // set bit at _Pos to false
fsb4000 marked this conversation as resolved.
Show resolved Hide resolved
return set(_Pos, false);
}

_NODISCARD bitset operator~() const noexcept { // flip all bits
_NODISCARD _CONSTEXPR23 bitset operator~() const noexcept { // flip all bits
bitset _Tmp = *this;
_Tmp.flip();
return _Tmp;
}

bitset& flip() noexcept { // flip all bits
_CONSTEXPR23 bitset& flip() noexcept { // flip all bits
for (size_t _Wpos = 0; _Wpos <= _Words; ++_Wpos) {
_Array[_Wpos] = ~_Array[_Wpos];
}
Expand All @@ -271,15 +290,15 @@ public:
return *this;
}

bitset& flip(size_t _Pos) { // flip bit at _Pos
_CONSTEXPR23 bitset& flip(size_t _Pos) { // flip bit at _Pos
fsb4000 marked this conversation as resolved.
Show resolved Hide resolved
if (_Bits <= _Pos) {
_Xran(); // _Pos off end
}

return _Flip_unchecked(_Pos);
}

_NODISCARD unsigned long to_ulong() const {
_NODISCARD _CONSTEXPR23 unsigned long to_ulong() const {
fsb4000 marked this conversation as resolved.
Show resolved Hide resolved
constexpr bool _Bits_zero = _Bits == 0;
constexpr bool _Bits_small = _Bits <= 32;
constexpr bool _Bits_large = _Bits > 64;
Expand All @@ -304,7 +323,7 @@ public:
}
}

_NODISCARD unsigned long long to_ullong() const {
_NODISCARD _CONSTEXPR23 unsigned long long to_ullong() const {
constexpr bool _Bits_zero = _Bits == 0;
constexpr bool _Bits_large = _Bits > 64;
if constexpr (_Bits_zero) {
Expand All @@ -323,7 +342,7 @@ public:
}

template <class _Elem = char, class _Tr = char_traits<_Elem>, class _Alloc = allocator<_Elem>>
_NODISCARD basic_string<_Elem, _Tr, _Alloc> to_string(
_NODISCARD _CONSTEXPR23 basic_string<_Elem, _Tr, _Alloc> to_string(
_Elem _Elem0 = static_cast<_Elem>('0'), _Elem _Elem1 = static_cast<_Elem>('1')) const {
fsb4000 marked this conversation as resolved.
Show resolved Hide resolved
// convert bitset to string
basic_string<_Elem, _Tr, _Alloc> _Str;
Expand All @@ -336,7 +355,7 @@ public:
return _Str;
}

_NODISCARD size_t count() const noexcept { // count number of set bits
_NODISCARD _CONSTEXPR23 size_t count() const noexcept { // count number of set bits
return _Select_popcount_impl<_Ty>([this](auto _Popcount_impl) {
size_t _Val = 0;
for (size_t _Wpos = 0; _Wpos <= _Words; ++_Wpos) {
Expand All @@ -351,8 +370,20 @@ public:
return _Bits;
}

_NODISCARD bool operator==(const bitset& _Right) const noexcept {
return _CSTD memcmp(&_Array[0], &_Right._Array[0], sizeof(_Array)) == 0;
_NODISCARD _CONSTEXPR23 bool operator==(const bitset& _Right) const noexcept {
#if _HAS_CXX23
if (_STD is_constant_evaluated()) {
for (size_t _Index = 0; _Index <= _Words; ++_Index) {
if (_Array[_Index] != _Right._Array[_Index]) {
return false;
}
}
return true;
} else
#endif // _HAS_CXX23
{
return _CSTD memcmp(&_Array[0], &_Right._Array[0], sizeof(_Array)) == 0;
}
}

#if !_HAS_CXX20
Expand All @@ -361,15 +392,15 @@ public:
}
#endif // !_HAS_CXX20

_NODISCARD bool test(size_t _Pos) const {
_NODISCARD _CONSTEXPR23 bool test(size_t _Pos) const {
fsb4000 marked this conversation as resolved.
Show resolved Hide resolved
if (_Bits <= _Pos) {
_Xran(); // _Pos off end
}

return _Subscript(_Pos);
}

_NODISCARD bool any() const noexcept {
_NODISCARD _CONSTEXPR23 bool any() const noexcept {
for (size_t _Wpos = 0; _Wpos <= _Words; ++_Wpos) {
if (_Array[_Wpos] != 0) {
return true;
Expand All @@ -379,11 +410,11 @@ public:
return false;
}

_NODISCARD bool none() const noexcept {
_NODISCARD _CONSTEXPR23 bool none() const noexcept {
return !any();
}

_NODISCARD bool all() const noexcept {
_NODISCARD _CONSTEXPR23 bool all() const noexcept {
constexpr bool _Zero_length = _Bits == 0;
if constexpr (_Zero_length) { // must test for this, otherwise would count one full word
return true;
Expand All @@ -399,13 +430,13 @@ public:
return _No_padding || _Array[_Words] == (static_cast<_Ty>(1) << (_Bits % _Bitsperword)) - 1;
}

_NODISCARD bitset operator<<(size_t _Pos) const noexcept {
_NODISCARD _CONSTEXPR23 bitset operator<<(size_t _Pos) const noexcept {
fsb4000 marked this conversation as resolved.
Show resolved Hide resolved
bitset _Tmp = *this;
_Tmp <<= _Pos;
return _Tmp;
}

_NODISCARD bitset operator>>(size_t _Pos) const noexcept {
_NODISCARD _CONSTEXPR23 bitset operator>>(size_t _Pos) const noexcept {
fsb4000 marked this conversation as resolved.
Show resolved Hide resolved
bitset _Tmp = *this;
_Tmp >>= _Pos;
return _Tmp;
Expand All @@ -421,14 +452,14 @@ private:
static constexpr ptrdiff_t _Bitsperword = CHAR_BIT * sizeof(_Ty);
static constexpr ptrdiff_t _Words = _Bits == 0 ? 0 : (_Bits - 1) / _Bitsperword; // NB: number of words - 1

void _Trim() noexcept { // clear any trailing bits in last word
_CONSTEXPR23 void _Trim() noexcept { // clear any trailing bits in last word
constexpr bool _Work_to_do = _Bits == 0 || _Bits % _Bitsperword != 0;
if constexpr (_Work_to_do) {
_Array[_Words] &= (_Ty{1} << _Bits % _Bitsperword) - 1;
}
}

bitset& _Set_unchecked(size_t _Pos, bool _Val) noexcept { // set bit at _Pos to _Val, no checking
_CONSTEXPR23 bitset& _Set_unchecked(size_t _Pos, bool _Val) noexcept { // set bit at _Pos to _Val, no checking
fsb4000 marked this conversation as resolved.
Show resolved Hide resolved
auto& _Selected_word = _Array[_Pos / _Bitsperword];
const auto _Bit = _Ty{1} << _Pos % _Bitsperword;
if (_Val) {
Expand All @@ -440,7 +471,7 @@ private:
return *this;
}

bitset& _Flip_unchecked(size_t _Pos) noexcept { // flip bit at _Pos, no checking
_CONSTEXPR23 bitset& _Flip_unchecked(size_t _Pos) noexcept { // flip bit at _Pos, no checking
fsb4000 marked this conversation as resolved.
Show resolved Hide resolved
_Array[_Pos / _Bitsperword] ^= _Ty{1} << _Pos % _Bitsperword;
return *this;
}
Expand All @@ -461,21 +492,21 @@ private:
};

template <size_t _Bits>
_NODISCARD bitset<_Bits> operator&(const bitset<_Bits>& _Left, const bitset<_Bits>& _Right) noexcept {
_NODISCARD _CONSTEXPR23 bitset<_Bits> operator&(const bitset<_Bits>& _Left, const bitset<_Bits>& _Right) noexcept {
bitset<_Bits> _Ans = _Left;
_Ans &= _Right;
return _Ans;
}

template <size_t _Bits>
_NODISCARD bitset<_Bits> operator|(const bitset<_Bits>& _Left, const bitset<_Bits>& _Right) noexcept {
_NODISCARD _CONSTEXPR23 bitset<_Bits> operator|(const bitset<_Bits>& _Left, const bitset<_Bits>& _Right) noexcept {
bitset<_Bits> _Ans = _Left;
_Ans |= _Right;
return _Ans;
}

template <size_t _Bits>
_NODISCARD bitset<_Bits> operator^(const bitset<_Bits>& _Left, const bitset<_Bits>& _Right) noexcept {
_NODISCARD _CONSTEXPR23 bitset<_Bits> operator^(const bitset<_Bits>& _Left, const bitset<_Bits>& _Right) noexcept {
bitset<_Bits> _Ans = _Left;
_Ans ^= _Right;
return _Ans;
Expand Down
2 changes: 2 additions & 0 deletions stl/inc/yvals_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,7 @@
// P2302R4 ranges::contains, ranges::contains_subrange
// P2321R2 zip
// (changes to pair, tuple, and vector<bool>::reference only)
// P2417R2 More constexpr bitset
// P2440R1 ranges::iota, ranges::shift_left, ranges::shift_right
// P2441R2 views::join_with
// P2442R1 Windowing Range Adaptors: views::chunk, views::slide
Expand Down Expand Up @@ -1456,6 +1457,7 @@

#define __cpp_lib_associative_heterogeneous_erasure 202110L
#define __cpp_lib_byteswap 202110L
#define __cpp_lib_constexpr_bitset 202207L
#define __cpp_lib_constexpr_typeinfo 202106L

#ifdef __cpp_lib_concepts
Expand Down
1 change: 1 addition & 0 deletions tests/std/test.lst
Original file line number Diff line number Diff line change
Expand Up @@ -491,6 +491,7 @@ tests\P2302R4_ranges_alg_contains_subrange
tests\P2321R2_proxy_reference
tests\P2401R0_conditional_noexcept_for_exchange
tests\P2415R2_owning_view
tests\P2417R2_constexpr_bitset
tests\P2440R1_ranges_alg_shift_left
tests\P2440R1_ranges_alg_shift_right
tests\P2440R1_ranges_numeric_iota
Expand Down
4 changes: 4 additions & 0 deletions tests/std/tests/P2417R2_constexpr_bitset/env.lst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Copyright (c) Microsoft Corporation.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

RUNALL_INCLUDE ..\usual_latest_matrix.lst
Loading