virtual parameters obtain their registry via ADL - #96
Open
jll63 wants to merge 4 commits into
Open
Conversation
|
An automated preview of the documentation is available at https://96.openmethod.prtest3.cppalliance.org/libs/openmethod/doc/html/index.html If more commits are pushed to the pull request, the docs will rebuild at the same URL. 2026-09-02 23:03:42 UTC |
jll63
force-pushed
the
feature/adl-default-registry
branch
from
September 2, 2026 13:50
60a423f to
0ef01ba
Compare
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## develop #96 +/- ##
===========================================
- Coverage 94.94% 92.75% -2.19%
===========================================
Files 99 22 -77
Lines 4373 1643 -2730
Branches 2168 505 -1663
===========================================
- Hits 4152 1524 -2628
+ Misses 162 71 -91
+ Partials 59 48 -11
... and 77 files with indirect coverage changes Continue to review full report in Codecov by Harness.
🚀 New features to boost your workflow:
|
A class can now name the registry it belongs to, once, next to itself:
class Animal {
friend auto boost_openmethod_registry(Animal*) -> zoo_registry;
};
The class then has an *affinity* for that registry, inherited by its derived
classes, and everything that mentions it finds it: `virtual_ptr`, its deduction
guides, `final_virtual_ptr`, the smart pointer aliases and factories, and any
method that takes the class as a virtual parameter. A method declared without a
registry argument takes the affinity its virtual parameters agree on.
`inplace_vptr.hpp` already had this hook, privately, returning `void` to mean
"no customization". Making the catch-all return BOOST_OPENMETHOD_DEFAULT_REGISTRY
instead lets it serve as a default template argument directly, and makes
backward compatibility structural: with no overload anywhere, every construct
resolves to what it resolved to before. `.text` for test_virtual_ptr_dispatch.cpp
is byte-identical, and the 530 defined symbols are unchanged.
Having *no* affinity is not the same as an affinity for the default registry -
only the former yields. That is what lets a method mix a class that has one with
a class that has none, so a first affinity does not cascade errors through a
codebase. Two conflicting affinities are diagnosed, as is a registry named on a
method that contradicts one of its parameters.
Deliberately out of scope, and documented as such: `virtual_` keeps its single
template parameter; `use_classes` still registers into the macro default unless
a registry is listed last; the `any` and `type_erasure` interop headers are
untouched.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QoMTqq3duJAptRAbCXgNh1
compile_fail_adl_registry_declared_mismatch only declared the method. The "registry mismatch" static_assert is a fold in `method`'s class body, so it fires when the class is instantiated - and declaring the method is not enough. gcc and clang instantiate it anyway through the static registrar; MSVC does not, so the file compiled and the compile-fail test failed on every Windows job. Call the method in main(), the way compile_fail_virtual_ptr_different_registries.cpp already does. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QoMTqq3duJAptRAbCXgNh1
"Affinity" is the term the documentation uses for the relation, so the query that reads it back should carry it too. `default_registry_of` also read badly where it mattered most: "Registry defaults to the default registry of Class". `affine_registry` was the other candidate and is worse - it predicates "affine" of the registry, when it is the class that has the affinity, and "affine" reads as affine geometry in a library whose flagship example dispatches on matrix types. The concept is adjusted to match the name. Every class now *has* a registry affinity: a declared one if it declares `boost_openmethod_registry`, the default affinity otherwise. A declared affinity wins over a default one, which is the same rule as before - a method may mix a class that declares an affinity with one that does not - but stated without the awkward "no affinity, which is not the same as an affinity for the default registry". It also removes a corner that framing had: a class declared explicitly to the default registry is no longer a special case, it simply has the default affinity like any other. detail::affinity_of becomes declared_affinity, and no_affinity becomes default_affinity, so the internals read the same way as the prose. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QoMTqq3duJAptRAbCXgNh1
develop adopted clang-format 22 in 6b02978; reflow the files this branch touches to match, so the diff carries no formatting noise. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QoMTqq3duJAptRAbCXgNh1
jll63
force-pushed
the
feature/adl-default-registry
branch
from
September 2, 2026 22:58
0ef01ba to
55b4446
Compare
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.
(Written by Claude Code, on behalf of @jll63.)
Closes #82.
A class can now name the registry it belongs to, once, next to itself:
The class then has an affinity for that registry, and everything that mentions
it finds it:
virtual_ptr, its two deduction guides,final_virtual_ptr, thesmart pointer aliases and their
make_*_virtualfactories, and any method thattakes the class as a virtual parameter. A method declared without a registry
argument takes the affinity its virtual parameters agree on.
Notes on the shape
Class*, notClass&as sketched in the issue. It matches the hookinplace_vptr.hppalready had, so those classes get the behaviour for free;pointers pass through the
...fallback safely, where a class lvalue is onlyconditionally supported; and an overload on
Base*ranks below an exactDerived*one, which is what lets one declaration cover a hierarchy while aderived class can still override it.
The catch-all returns
BOOST_OPENMETHOD_DEFAULT_REGISTRY, notvoid.inplace_vptr's private catch-all returnedvoidto mean "no customization";returning the default registry instead makes the result usable as a default
template argument directly, and makes backward compatibility structural rather
than special-cased.
inplace_vptr's copy is removed in favour of the shared one.No affinity is not an affinity for the default registry. Only the first
yields, so a method may mix a class that has an affinity with one that has none
— a first affinity does not cascade errors through a codebase. Two conflicting
affinities are diagnosed, as is a registry named on a method that contradicts
one of its parameters.
A class whose base's overload cannot be used is diagnosed, not defaulted. An
ambiguous or inaccessible base conversion is a substitution failure, so a class
with two differently-hooked bases, a private hooked base, or a repeated
non-virtual hooked base gets a message telling it to declare its own.
Compatibility
With no overload anywhere the catch-all answers for every class, so
default_registry_of<T>isBOOST_OPENMETHOD_DEFAULT_REGISTRYand nothingchanges. Measured rather than argued: for
test_virtual_ptr_dispatch.cppat-O2 -g0,.textis byte-identical and all 530 defined symbols are unchanged.No existing spelling changes meaning or stops compiling, including
BOOST_OPENMETHOD(..., R)over an unhookedvirtual_<T>.Deliberately out of scope
virtual_keeps its single template parameter. Giving it aRegistrywouldcost a mangled-name change for every
method<...>mentioning it, ninepattern-match edits in
core.hpp, and twelve specializations in theanyandtype_erasureheaders. Scanning the parameter list reaches the same place.use_classes/BOOST_OPENMETHOD_CLASSESstill register into the macrodefault unless a registry is listed last. Registering a class that has an
affinity without naming its registry is a run-time
missing_class, not acompile error — documented with a warning, and the obvious follow-up.
anyandtype_erasureinterop headers are untouched.Tests and docs
Eight new tests and four compile-fail tests. 160/160 pass under gcc 13.3
Release, clang 18.1 Release, and gcc Debug (runtime checks), all with
BOOST_OPENMETHOD_WARNINGS_AS_ERRORS=ON. Documentation introduces "registryaffinity" as the term, in
registries_and_policies.adoc, with a new example;mrdocs.ymlstops excluding the hook, so it anddefault_registry_ofnow havereference pages.
Not covered here: the
dynamic_loadingandimplicit_shared_librariessuites,which the CMake configuration used skips with
BUILD_SHARED_LIBS=OFF.🤖 Generated with Claude Code
https://claude.ai/code/session_01QoMTqq3duJAptRAbCXgNh1