|
| 1 | +<?xml version='1.0' encoding='utf-8' standalone='no'?> |
| 2 | +<!DOCTYPE issue SYSTEM "lwg-issue.dtd"> |
| 3 | + |
| 4 | +<issue num="4187" status="New"> |
| 5 | +<title>`bitset::reference` should be const-assignable</title> |
| 6 | +<section><sref ref="[template.bitset]"/></section> |
| 7 | +<submitter>Arthur O'Dwyer</submitter> |
| 8 | +<date>21 Dec 2024</date> |
| 9 | +<priority>99</priority> |
| 10 | + |
| 11 | +<discussion> |
| 12 | +<p> |
| 13 | +LWG <iref ref="3638"/>, which proposes changes to <tt>vector<bool>::reference</tt>, is related. |
| 14 | +Should <tt>vector<bool>::reference</tt> and <tt>bitset<N>::reference</tt> behave differently |
| 15 | +in any respect? I think there's no good reason for them to behave differently, and good technical |
| 16 | +incentives to permit them to behave the same. We already have implementation divergence: libc++ makes |
| 17 | +`bitset::reference` const-assignable, whereas libstdc++ and MS STL do not. This means that libc++'s |
| 18 | +`bitset::reference` successfully avoids false positives from Arthur's proposed -Wassign-to-class-rvalue |
| 19 | +diagnostic, while libstdc++'s does not (See <a href="https://godbolt.org/z/4e96j7rvv">Godbolt</a>). |
| 20 | +<p/> |
| 21 | +The proposed resolution applies <a href="https://wg21.link/P2321#vectorboolreference">P2321</a>'s approach. We |
| 22 | +can't just insert `const` into the existing spec, because ABI. But also, since our goal is consistency |
| 23 | +with the post-P2321 <tt>vector<bool>::reference</tt>, we should do the same thing here as P2321, not invent anything novel. |
| 24 | +<p/> |
| 25 | +Open questions related to the current P/R: |
| 26 | +</p> |
| 27 | +<ol> |
| 28 | +<li><p>LWG 3638 proposes to add these three `swap` overloads to <tt>vector<bool>::reference</tt>. |
| 29 | +Should we also, consistently, add them to `bitset::reference`? I think we should.</p> |
| 30 | +<blockquote><pre> |
| 31 | +friend constexpr void swap(reference x, reference y) noexcept; |
| 32 | +friend constexpr void swap(reference x, bool& y) noexcept; |
| 33 | +friend constexpr void swap(bool& x, reference y) noexcept; |
| 34 | +</pre></blockquote> |
| 35 | +</li> |
| 36 | +<li><p>Both <tt>vector<bool>::reference</tt> and `bitset::reference` right now are specified with</p> |
| 37 | +<blockquote><pre> |
| 38 | +constexpr reference(const reference&) = default; |
| 39 | +</pre></blockquote> |
| 40 | +<p>which is meaningless because we don't know the data members of `reference`. So this isn't actually |
| 41 | +specifying that the constructor is trivial, let alone that it's `noexcept`. I think we should re-specify |
| 42 | +both types' copy constructors as simply `constexpr` and `noexcept`; and then if we want them to be trivial, |
| 43 | +we should say so in English prose.</p> |
| 44 | +</li> |
| 45 | +</ol> |
| 46 | +</discussion> |
| 47 | + |
| 48 | +<resolution> |
| 49 | +<p> |
| 50 | +This wording is relative to <paper num="N5001"/>. |
| 51 | +</p> |
| 52 | + |
| 53 | +<ol> |
| 54 | +<li><p>Modify <sref ref="[template.bitset.general]"/> as indicated:</p> |
| 55 | + |
| 56 | +<blockquote> |
| 57 | +<pre> |
| 58 | +namespace std { |
| 59 | + template<size_t N> class bitset { |
| 60 | + public: |
| 61 | + // <i>bit reference</i> |
| 62 | + class reference { |
| 63 | + public: |
| 64 | + constexpr reference(const reference&) = default; |
| 65 | + constexpr ~reference(); |
| 66 | + constexpr reference& operator=(bool x) noexcept; // <i>for b[i] = x;</i> |
| 67 | + constexpr reference& operator=(const reference&) noexcept; // <i>for b[i] = b[j];</i> |
| 68 | + <ins>constexpr const reference& operator=(bool x) const noexcept;</ins> |
| 69 | + constexpr bool operator~() const noexcept; // <i>flips the bit</i> |
| 70 | + constexpr operator bool() const noexcept; // <i>for x = b[i];</i> |
| 71 | + constexpr reference& flip() noexcept; // <i>for b[i].flip();</i> |
| 72 | + <ins>friend constexpr void swap(reference x, reference y) noexcept; |
| 73 | + friend constexpr void swap(reference x, bool& y) noexcept; |
| 74 | + friend constexpr void swap(bool& x, reference y) noexcept;</ins> |
| 75 | + }; |
| 76 | + […] |
| 77 | + }; |
| 78 | + […] |
| 79 | +} |
| 80 | +</pre> |
| 81 | +</blockquote> |
| 82 | + |
| 83 | + |
| 84 | +</li> |
| 85 | + |
| 86 | +</ol> |
| 87 | +</resolution> |
| 88 | + |
| 89 | +</issue> |
0 commit comments