fix: Remove explicit from std/boost hash specialisation default constructors - #8100
Merged
bthomee merged 1 commit intoAug 25, 2026
Conversation
…structors
std::hash<T> (and boost::hash<T>) specialisations must be default-constructible in
copy-initialisation contexts because the standard library relies on this in
several places (e.g. libstdc++'s _Hashtable_ebo_helper value-initialises the
hasher via _M_hash{}, and std::tuple's primary constructor evaluates
__is_implicitly_default_constructible_v on every element -- both are
copy-initialisation contexts).
An 'explicit' default constructor makes these ill-formed. This was previously
latent because no unordered container was keyed on the affected types in a
context that triggered the instantiation chain; GCC 15 also tightened its
diagnostics for [[no_unique_address]] EBO members with explicit defaulted
constructors.
Aligns these specialisations with the existing convention already used by
std::hash<xrpl::uint256>, std::hash<xrpl::Currency>, std::hash<xrpl::NodeID>,
std::hash<xrpl::Directory>, and std::hash<xrpl::AccountID>.
a1q123456
marked this pull request as ready for review
August 24, 2026 16:48
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
bthomee
enabled auto-merge
August 25, 2026 13:32
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
High Level Overview of Change
Remove the
explicitkeyword from the defaulted default constructor of fivestd::hash<T>/boost::hash<T>specialisations inlibxrpl:std::hash<xrpl::MPTID>(include/xrpl/protocol/MPTIssue.h)std::hash<xrpl::MPTIssue>,std::hash<xrpl::Asset>(include/xrpl/protocol/Book.h)boost::hash<xrpl::MPTIssue>,boost::hash<xrpl::Asset>(include/xrpl/protocol/Book.h)boost::hash<::beast::ip::Address>(include/xrpl/beast/net/IPAddress.h)No behavioural change; this aligns them with the convention already used by every other hash specialisation in the codebase (
std::hash<xrpl::uint256>,std::hash<xrpl::Currency>,std::hash<xrpl::NodeID>,std::hash<xrpl::Directory>,std::hash<xrpl::AccountID>, and the twostd::hash<xrpl::Issue>/std::hash<xrpl::Book>variants).Context of Change
Both
std::hash<T>andboost::hash<T>are required by their respective specifications to satisfy the Hash requirements, which includeCpp17DefaultConstructible. That requirement mandates the type be default-constructible in copy-initialisation contexts (i.e.T u{};andT v = {};must be well-formed), not just direct-initialisation.Marking the defaulted default constructor
explicitviolates this: it makes copy/value-initialisation ill-formed while direct-init (T{}as a prvalue expression,T()as an operand) still compiles. This is why the bug was latent -- most direct call sitesstd::hash<T>{}(x)are direct-init and work either way. It only bites when a hasher is value-initialised inside a standard/boost library internal that lives in a copy-initialisation context, for example:_Hashtable_ebo_helper<_Hash>::_M_hash{}inside a defaulted constructor of_Hash_code_base.std::tuple's primary constructor evaluating__is_implicitly_default_constructible_von every element, which recursively probes each member viarequires (void(&f)(T)) { f({}); }(copy-list-initialisation).boost::unordered_*internals that value-initialise the hasher the same way libstdc++ does.GCC 15 additionally tightened its diagnostics for
[[no_unique_address]]EBO members withexplicitdefaulted constructors, which is what surfaces this at build time.The cleanup is exhaustive: after this change, no
hash<...>specialisation anywhere underinclude/orsrc/has anexplicitdefault constructor.Type of Change
.gitignore, formatting, dropping old tests)API Impact
libxrplAPI)Test Plan
Existing compile-time and runtime coverage is sufficient: every use of the affected specialisations goes through the same hash containers already exercised by existing unit tests. No behavioural change is possible from removing
expliciton a= defaulted default constructor -- the constructor body is unchanged. The fix is verified simply by the codebase compiling on GCC 15, where the previous form failed.