refactor: C++20 operators #33771

pull purpleKarrot wants to merge 2 commits into bitcoin:master from purpleKarrot:cxx20-operators changing 14 files +7 −106
  1. purpleKarrot commented at 1:49 pm on November 3, 2025: contributor

    Remove all operator!= definitions and provide operator<=> as a replacement where all relational comparison operators were defined before.

    The compiler is able to deduce missing comparison operators from operator!= and operator<=>. The compiler provided operators have the following advantages:

    1. less code
    2. guaranteed consistency

    Refactoring that changes the implementation, or replaces it with = default is left for a separate PR.

  2. refactor: Remove all `operator!=` definitions
    The compiler can deduce `operator!=` from `operator==`.
    5a0f49bd26
  3. refactor: Prefer `<=>` over multiple relational operators
    Define `operator<=>` in classes that have all of `<`, `<=`, `>`, `>=`.
    48840bfc2d
  4. DrahtBot added the label Refactoring on Nov 3, 2025
  5. DrahtBot commented at 1:49 pm on November 3, 2025: contributor

    The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

    Code Coverage & Benchmarks

    For details see: https://corecheck.dev/bitcoin/bitcoin/pulls/33771.

    Reviews

    See the guideline for information on the review process.

    Type Reviewers
    ACK stickies-v, optout21

    If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update.

    Conflicts

    Reviewers, this pull request conflicts with the following ones:

    • #33772 (prevector: simplify implementation of comparison operators and match behavior of std::vector by purpleKarrot)

    If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

  6. in src/script/script.h:273 in 48840bfc2d
    269@@ -270,18 +270,10 @@ class CScriptNum
    270     }
    271 
    272     inline bool operator==(const int64_t& rhs) const    { return m_value == rhs; }
    273-    inline bool operator!=(const int64_t& rhs) const    { return m_value != rhs; }
    274-    inline bool operator<=(const int64_t& rhs) const    { return m_value <= rhs; }
    275-    inline bool operator< (const int64_t& rhs) const    { return m_value <  rhs; }
    276-    inline bool operator>=(const int64_t& rhs) const    { return m_value >= rhs; }
    277-    inline bool operator> (const int64_t& rhs) const    { return m_value >  rhs; }
    278+    inline auto operator<=>(const int64_t& rhs) const    { return m_value <=> rhs; }
    


    stickies-v commented at 4:19 pm on November 3, 2025:

    nit (here and for all other new operator<=>): perhaps better to be explicit about the std::strong_ordering return type? And perhaps making it constexpr while touching?

      0diff --git a/src/prevector.h b/src/prevector.h
      1index d4d90c7350..595be4a603 100644
      2--- a/src/prevector.h
      3+++ b/src/prevector.h
      4@@ -7,6 +7,7 @@
      5 
      6 #include <algorithm>
      7 #include <cassert>
      8+#include <compare>
      9 #include <cstddef>
     10 #include <cstdint>
     11 #include <cstdlib>
     12@@ -71,8 +72,8 @@ public:
     13         iterator& operator+=(size_type n) { ptr += n; return *this; }
     14         iterator operator-(size_type n) const { return iterator(ptr - n); }
     15         iterator& operator-=(size_type n) { ptr -= n; return *this; }
     16-        bool operator==(iterator x) const { return ptr == x.ptr; }
     17-        auto operator<=>(iterator x) const { return ptr <=> x.ptr; }
     18+        constexpr bool operator==(iterator x) const { return ptr == x.ptr; }
     19+        constexpr std::strong_ordering operator<=>(iterator x) const { return ptr <=> x.ptr; }
     20     };
     21 
     22     class const_iterator {
     23@@ -99,8 +100,8 @@ public:
     24         const_iterator& operator+=(size_type n) { ptr += n; return *this; }
     25         const_iterator operator-(size_type n) const { return const_iterator(ptr - n); }
     26         const_iterator& operator-=(size_type n) { ptr -= n; return *this; }
     27-        bool operator==(const_iterator x) const { return ptr == x.ptr; }
     28-        auto operator<=>(const_iterator x) const { return ptr <=> x.ptr; }
     29+        constexpr bool operator==(const_iterator x) const { return ptr == x.ptr; }
     30+        constexpr std::strong_ordering operator<=>(const_iterator x) const { return ptr <=> x.ptr; }
     31     };
     32 
     33 private:
     34diff --git a/src/script/script.h b/src/script/script.h
     35index b06be9c975..f1472a7dd3 100644
     36--- a/src/script/script.h
     37+++ b/src/script/script.h
     38@@ -14,6 +14,7 @@
     39 #include <util/hash_type.h>
     40 
     41 #include <cassert>
     42+#include <compare>
     43 #include <cstdint>
     44 #include <cstring>
     45 #include <limits>
     46@@ -269,11 +270,11 @@ public:
     47         m_value = set_vch(vch);
     48     }
     49 
     50-    inline bool operator==(const int64_t& rhs) const    { return m_value == rhs; }
     51-    inline auto operator<=>(const int64_t& rhs) const    { return m_value <=> rhs; }
     52+    inline constexpr bool operator==(const int64_t& rhs) const    { return m_value == rhs; }
     53+    inline constexpr std::strong_ordering operator<=>(const int64_t& rhs) const    { return m_value <=> rhs; }
     54 
     55-    inline bool operator==(const CScriptNum& rhs) const { return operator==(rhs.m_value); }
     56-    inline auto operator<=>(const CScriptNum& rhs) const { return operator<=>(rhs.m_value); }
     57+    inline constexpr bool operator==(const CScriptNum& rhs) const { return operator==(rhs.m_value); }
     58+    inline constexpr std::strong_ordering operator<=>(const CScriptNum& rhs) const { return operator<=>(rhs.m_value); }
     59 
     60     inline CScriptNum operator+(   const int64_t& rhs)    const { return CScriptNum(m_value + rhs);}
     61     inline CScriptNum operator-(   const int64_t& rhs)    const { return CScriptNum(m_value - rhs);}
     62diff --git a/src/test/scriptnum10.h b/src/test/scriptnum10.h
     63index 402606714d..fd112d6ff7 100644
     64--- a/src/test/scriptnum10.h
     65+++ b/src/test/scriptnum10.h
     66@@ -7,6 +7,7 @@
     67 #define BITCOIN_TEST_SCRIPTNUM10_H
     68 
     69 #include <cassert>
     70+#include <compare>
     71 #include <cstdint>
     72 #include <limits>
     73 #include <stdexcept>
     74@@ -60,11 +61,11 @@ public:
     75         m_value = set_vch(vch);
     76     }
     77 
     78-    inline bool operator==(const int64_t& rhs) const    { return m_value == rhs; }
     79-    inline auto operator<=>(const int64_t& rhs) const    { return m_value <=> rhs; }
     80+    inline constexpr bool operator==(const int64_t& rhs) const    { return m_value == rhs; }
     81+    inline constexpr std::strong_ordering operator<=>(const int64_t& rhs) const    { return m_value <=> rhs; }
     82 
     83-    inline bool operator==(const CScriptNum10& rhs) const { return operator==(rhs.m_value); }
     84-    inline auto operator<=>(const CScriptNum10& rhs) const { return operator<=>(rhs.m_value); }
     85+    inline constexpr bool operator==(const CScriptNum10& rhs) const { return operator==(rhs.m_value); }
     86+    inline constexpr std::strong_ordering operator<=>(const CScriptNum10& rhs) const { return operator<=>(rhs.m_value); }
     87 
     88     inline CScriptNum10 operator+(   const int64_t& rhs)    const { return CScriptNum10(m_value + rhs);}
     89     inline CScriptNum10 operator-(   const int64_t& rhs)    const { return CScriptNum10(m_value - rhs);}
     90diff --git a/src/util/bitdeque.h b/src/util/bitdeque.h
     91index 21934e02da..be3e0fd859 100644
     92--- a/src/util/bitdeque.h
     93+++ b/src/util/bitdeque.h
     94@@ -6,6 +6,7 @@
     95 #define BITCOIN_UTIL_BITDEQUE_H
     96 
     97 #include <bitset>
     98+#include <compare>
     99 #include <cstddef>
    100 #include <deque>
    101 #include <limits>
    102@@ -99,8 +100,8 @@ class bitdeque
    103         friend Iterator operator+(Iterator x, difference_type dist) { x += dist; return x; }
    104         friend Iterator operator+(difference_type dist, Iterator x) { x += dist; return x; }
    105         friend Iterator operator-(Iterator x, difference_type dist) { x -= dist; return x; }
    106-        friend auto operator<=>(const Iterator& x, const Iterator& y) { return std::tie(x.m_it, x.m_bitpos) <=> std::tie(y.m_it, y.m_bitpos); }
    107-        friend bool operator==(const Iterator& x, const Iterator& y) { return x.m_it == y.m_it && x.m_bitpos == y.m_bitpos; }
    108+        friend constexpr std::strong_ordering operator<=>(const Iterator& x, const Iterator& y) { return std::tie(x.m_it, x.m_bitpos) <=> std::tie(y.m_it, y.m_bitpos); }
    109+        friend constexpr bool operator==(const Iterator& x, const Iterator& y) { return x.m_it == y.m_it && x.m_bitpos == y.m_bitpos; }
    110         reference operator*() const { return (*m_it)[m_bitpos]; }
    111         reference operator[](difference_type pos) const { return *(*this + pos); }
    112     };
    

    purpleKarrot commented at 5:23 pm on November 3, 2025:

    Thanks @stickies-v.

    I am not convinced about std::strong_ordering. constexpr will definitely be added as a follow up, together with = default where appropriate.

  7. stickies-v approved
  8. stickies-v commented at 4:19 pm on November 3, 2025: contributor
    utACK 48840bfc2d7beeac0ddf56a3c26b243156ec8936. Pretty straightforward cleanup taking advantage of C++20 improvements, nice.
  9. optout21 commented at 2:37 pm on November 11, 2025: none

    utACK 48840bfc2d7beeac0ddf56a3c26b243156ec8936

    Straightforward refactoring resulting in code removal 😎 First commit removes != operator where == exits. Second commit replaces 4 comparison operators with the new <=> spaceship operator. My only concern is that competence with the new <=> operator may not be extensive across the developer community of this project, but hey, it’s time to learn!

  10. optout21 commented at 2:38 pm on November 11, 2025: none
    I wonder whether it would it be possible check for superfluous comparison operator implementations in linting?

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2025-11-23 00:13 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me