Skip to content

Commit 2f5636b

Browse files
jll63claude
andcommitted
fix: unbreak the GCC build, and address review of the registry recipe
The doc comment added for BOOST_OPENMETHOD_DEFAULT_REGISTRY ended a `//!` line with a backslash, making it a line continuation. GCC's -Wcomment (in -Wall) rejects that under -Werror, so every GCC job on both CIs failed while every clang, MSVC and Xcode job passed. Put the #define on one line. Verified by reproducing the exact diagnostic with the pre-fix header and confirming g++ -Wall -Wextra -Werror accepts the fixed one. Restore the coverage lost with deferred_custom_rtti.cpp. That example was the only place combining deferred_static_rtti with virtual bases and dynamic_cast_ref: test_custom_rtti_virtual_base.cpp has the virtual bases and the cast but derives from policies::rtti, and test_custom_rtti_deferred.cpp had neither. Add Bat and Owl, virtually derived, plus the dynamic_cast_ref the cast now needs - `requires_dynamic_cast` is true exactly when static_cast is ill-formed, so these overriders reach the policy hook. Confirmed by sabotaging dynamic_cast_ref and watching the test fail. Name core.hpp, not <boost/openmethod.hpp>, as the point where the macro is read. initialize.hpp, inplace_vptr.hpp and every interop/*.hpp also include core.hpp, so a TU that includes one of those before the #define binds silently to default_registry. Four places still said otherwise. test_capture_errors.hpp now owns the whole recipe - declaration, #define, include and test_registry - instead of the seven tests repeating it. There is no ordering left for a caller to get wrong, which is what the previous version's comment had claimed without being able to guarantee it. Those tests no longer name the macro, so test/CMakeLists.txt would have handed them the shared PCH and silently defeated the override; teach its scan to follow the header too. Documentation fixes from the same review: - ref_headers.adoc claimed every stock policy has its own header; indirect_vptr, runtime_checks and deferred_static_rtti live in preamble.hpp. Say so, and note runtime_checks joins default_registry under BOOST_OPENMETHOD_ENABLE_RUNTIME_CHECKS. - custom_rtti.adoc pointed at a declaration "at the top of the file" that sits below the classes listing, and its Deferred RTTI section never showed the declaration step at all - example 2's setup and registry tags were unrendered. - error_handling.adoc's listing opened with five lines of registry boilerplate its prose never introduced. - shared_libraries.adoc's my_registry.hpp is a complete header now, so give it the include guard the animals.hpp it is compared to has. - CLAUDE.md cited a line number that had already moved, pointed at greps in a section that has none, miscounted the files carrying the macro, and described an unqualified `registry` as resolving silently when it is a hard error. Remove doc/modules/ROOT/examples/static_rtti.cpp: an orphan no page references, left marker-free by the previous commit, duplicating snippets/static_rtti.cpp - which exercises the same policy, classes and dispatch, is the copy the docs render, and asserts more. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
1 parent 64c17b9 commit 2f5636b

21 files changed

Lines changed: 209 additions & 156 deletions

CLAUDE.md

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -335,10 +335,15 @@ is a single symbol) and `test/implicit_shared_libraries/`.
335335

336336
### Overriding the default registry
337337

338-
The registry is **forward-declared** before `<boost/openmethod.hpp>` and **defined after** it.
339-
Do not reintroduce the old "include a pre-core header, define the registry, `#define`, then
340-
include" idiom - `preamble.hpp` and `default_registry.hpp` appear nowhere outside `include/`,
341-
and the greps in *Development Workflow* enforce that.
338+
The registry is **forward-declared** before `core.hpp` - or any header that includes it,
339+
`<boost/openmethod.hpp>` among them - and **defined after**. Do not reintroduce the old
340+
"include a pre-core header, define the registry, `#define`, then include" idiom:
341+
`preamble.hpp` and `default_registry.hpp` should appear nowhere outside `include/`. Nothing
342+
enforces that automatically; check it by hand when touching this area:
343+
344+
```bash
345+
git grep -n "openmethod/preamble.hpp\|openmethod/default_registry.hpp" -- doc test
346+
```
342347

343348
```cpp
344349
struct my_registry;
@@ -370,18 +375,22 @@ rules:
370375
- The registry must be **complete** before the first construct that instantiates it: a
371376
`BOOST_OPENMETHOD*` macro, `use_classes`, `method`, `virtual_ptr`, `inplace_vptr_base`,
372377
`initialize()`, or `BOOST_OPENMETHOD_{IMPORT,EXPORT,INSTANTIATE}_REGISTRY`. Violating this is
373-
a hard error (`incomplete type ... used in nested name specifier`, `core.hpp:376`) - never
374-
silent.
378+
a hard error (`incomplete type ... used in nested name specifier`, from `use_class_aux` in
379+
`core.hpp`) - never silent.
375380
- It must name a **class**, declared with the same class-key (`struct`) as the definition. A
376381
`class`/`struct` mismatch is MSVC C4099, an error under the suite's `/W4 /WX`.
377-
- **Qualify** the name if it could also be found in `namespace boost::openmethod`.
378-
`#define BOOST_OPENMETHOD_DEFAULT_REGISTRY registry` silently resolves to
379-
`boost::openmethod::registry` and fails with `missing template arguments`; `::registry` works.
380-
381-
`test/CMakeLists.txt` scans each `test_*.cpp` for the token `BOOST_OPENMETHOD_DEFAULT_REGISTRY`
382-
and withholds the shared PCH from any file that has it - a force-included PCH would still
383-
precede the `#define`. That detection is unaffected by the ordering, but the count matters:
384-
17 files under `test/` carry the macro.
382+
- **Qualify** the name if it could also be found in `namespace boost::openmethod`. The macro
383+
is expanded inside that namespace, so `#define BOOST_OPENMETHOD_DEFAULT_REGISTRY registry`
384+
binds to `boost::openmethod::registry` rather than the global one. That one is loud -
385+
`missing template arguments` - but a name that *does* resolve would bind to the wrong type
386+
silently. `::registry` works.
387+
388+
`test/CMakeLists.txt` withholds the shared PCH from any `test_*.cpp` that overrides the
389+
registry - a force-included PCH would still precede the `#define`. It detects them by scanning
390+
for the token `BOOST_OPENMETHOD_DEFAULT_REGISTRY` **or** for an include of a header that
391+
carries the override on the file's behalf (`test_capture_errors.hpp`). Add another such header
392+
and the scan has to learn about it: miss one and the file still compiles, binds to
393+
`default_registry`, and fails at run time.
385394

386395
### Custom RTTI
387396
When `<typeinfo>` is unavailable or insufficient, use static_rtti or implement custom RTTI. See `doc/modules/ROOT/examples/custom_rtti/` and policies in `include/boost/openmethod/policies/`.

doc/modules/ROOT/examples/static_rtti.cpp

Lines changed: 0 additions & 51 deletions
This file was deleted.

doc/modules/ROOT/pages/custom_rtti.adoc

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,8 @@ two lines before the library is included: a declaration of the registry class,
9292
and a definition of
9393
xref:reference:BOOST_OPENMETHOD_DEFAULT_REGISTRY.adoc[BOOST_OPENMETHOD_DEFAULT_REGISTRY]
9494
naming it. The registry itself comes further down; only its _name_ has to be
95-
known when `<boost/openmethod.hpp>` is parsed.
95+
known when `<boost/openmethod/core.hpp>` is parsed - which any header that
96+
includes it, `<boost/openmethod.hpp>` among them, does for you.
9697
9798
[source,c++]
9899
----
@@ -135,8 +136,8 @@ small, dense range. It means that we can use them as indexes in a vector.
135136
include::{example}/1/custom_rtti.cpp[tag=registry]
136137
----
137138
138-
This is the definition promised by the declaration at the top of the file. It
139-
must appear before the first `BOOST_OPENMETHOD`, `BOOST_OPENMETHOD_OVERRIDE` or
139+
This is the definition promised by the declaration shown above. It must appear
140+
before the first `BOOST_OPENMETHOD`, `BOOST_OPENMETHOD_OVERRIDE` or
140141
`BOOST_OPENMETHOD_CLASSES`: those instantiate the registry, and an incomplete
141142
type will not do.
142143
@@ -173,3 +174,16 @@ postpones reading the type ids until `initialize` is called:
173174
----
174175
include::{example}/2/custom_rtti.cpp[tag=policy]
175176
----
177+
178+
The setup is the same as before - the registry is declared, named as the default,
179+
and defined once the library is in scope:
180+
181+
[source,c++]
182+
----
183+
include::{example}/2/custom_rtti.cpp[tag=setup]
184+
----
185+
186+
[source,c++]
187+
----
188+
include::{example}/2/custom_rtti.cpp[tag=registry]
189+
----

doc/modules/ROOT/pages/error_handling.adoc

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,12 @@ not implemented
2424
spin
2525
----
2626

27-
We can also replace the `error_handler` policy with our own.
28-
For example:
27+
We can also replace the `error_handler` policy with our own. Since the handler
28+
is part of the registry, this means overriding the default registry: the
29+
listing opens by declaring `custom_registry` and naming it in
30+
xref:reference:BOOST_OPENMETHOD_DEFAULT_REGISTRY.adoc[BOOST_OPENMETHOD_DEFAULT_REGISTRY],
31+
then defines it further down, once the policy it is built from exists. See
32+
xref:registries_and_policies.adoc[Registries and Policies] for that recipe.
2933

3034

3135
[source,c++]

doc/modules/ROOT/pages/ref_headers.adoc

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ parameters.
106106

107107
## Policy Headers
108108

109-
Each stock policy lives in a header of its own. The five that make up
109+
Most stock policies live in a header of their own. Those that make up
110110
cpp:default_registry[] come in with `<boost/openmethod.hpp>`; the others are
111111
included explicitly. A policy header depends on nothing but the library's
112112
foundations, so it may be included in any order relative to
@@ -115,6 +115,11 @@ that overrides
115115
xref:reference:BOOST_OPENMETHOD_DEFAULT_REGISTRY.adoc[`BOOST_OPENMETHOD_DEFAULT_REGISTRY`]
116116
puts it.
117117

118+
Three policies have no header of their own: cpp:indirect_vptr[],
119+
cpp:runtime_checks[] and cpp:deferred_static_rtti[] are defined alongside
120+
`registry` itself, and are available as soon as `<boost/openmethod.hpp>` has
121+
been included.
122+
118123
### link:{headers-url}/boost/openmethod/policies/std_rtti.hpp[<boost/openmethod/policies/std_rtti.hpp>]
119124

120125
Provides an implementation of the `rtti` policy using standard RTTI. Part of
@@ -142,6 +147,10 @@ the library aborts the program. Part of `default_registry`.
142147
Provides an implementation of the `output` policy that writes diagnostics to
143148
the C standard error stream (not using iostreams). Part of `default_registry`.
144149

150+
NOTE: `default_registry` also contains `runtime_checks` when
151+
xref:reference:BOOST_OPENMETHOD_ENABLE_RUNTIME_CHECKS.adoc[`BOOST_OPENMETHOD_ENABLE_RUNTIME_CHECKS`]
152+
is defined. That policy needs no header - see above.
153+
145154
### link:{headers-url}/boost/openmethod/policies/static_rtti.hpp[<boost/openmethod/policies/static_rtti.hpp>]
146155

147156
Provides a minimal implementation of the `rtti` policy that does not depend on

doc/modules/ROOT/pages/registries_and_policies.adoc

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,16 @@ different registries, it must be registered with each of them.
77

88
Class templates cpp:use_classes[], cpp:method[], cpp:virtual_ptr[], and macros
99
xref:reference:BOOST_OPENMETHOD.adoc[BOOST_OPENMETHOD] and
10-
xref:reference:BOOST_OPENMETHOD_CLASSES.adoc[BOOST_OPENMETHOD_CLASSES], take an additional
11-
argument, a cpp:registry[] class, which defaults to cpp:default_registry[]. The
12-
default registry can be overridden by defining the macroprocessor symbol
10+
xref:reference:BOOST_OPENMETHOD_CLASSES.adoc[BOOST_OPENMETHOD_CLASSES], take an
11+
additional argument, a cpp:registry[] class, which defaults to
12+
cpp:default_registry[]. The default registry can be overridden by defining the
13+
preprocessor symbol
1314
xref:reference:BOOST_OPENMETHOD_DEFAULT_REGISTRY.adoc[BOOST_OPENMETHOD_DEFAULT_REGISTRY]
14-
_before_ including `<boost/openmethod.hpp>`. The value of the symbol is used as
15-
a default template parameter for `use_classes`, `method`, `virtual_ptr`, and
16-
others. Once the header has been included, changing
17-
`BOOST_OPENMETHOD_DEFAULT_REGISTRY` has no effect.
15+
_before_ including `<boost/openmethod/core.hpp>` (or any header that includes
16+
it, like `<boost/openmethod.hpp>`). The value of the symbol is used as a default
17+
template parameter for `use_classes`, `method`, `virtual_ptr`, and others. Once
18+
it has been included, changing `BOOST_OPENMETHOD_DEFAULT_REGISTRY` has no
19+
effect.
1820

1921
For a registry the library provides, that is the whole recipe:
2022

@@ -84,7 +86,7 @@ Policies are placed in the cpp:boost::openmethod::policies[] namespace.
8486

8587
|===
8688

87-
if
89+
If
8890
xref:reference:BOOST_OPENMETHOD_ENABLE_RUNTIME_CHECKS.adoc[BOOST_OPENMETHOD_ENABLE_RUNTIME_CHECKS]
8991
is defined, `default_registry` also contains the `runtime_checks` policy. This
9092
enables extra validations during method dispatch, which can detect missing class
@@ -148,7 +150,7 @@ left to right; cpp:finalize[] calls each policy's `finalize` in the reverse
148150
order. A policy that depends on another policy having been initialized must
149151
therefore be listed _after_ its dependency. In particular, `vptr_vector` reads
150152
the state of the `type_hash` policy, so the `type_hash` policy must come before
151-
`vptr_vector` as in `default_registry` above, where `fast_perfect_hash`
153+
`vptr_vector` - as in `default_registry` above, where `fast_perfect_hash`
152154
precedes `vptr_vector`. This particular requirement is enforced with a
153155
`static_assert`.
154156

@@ -162,7 +164,7 @@ struct indirect_registry : default_registry::with<policies::indirect_vptr> {};
162164
----
163165

164166
Policies are implemented as unary
165-
https://www.boost.org/doc/libs/1_89_0/libs/mp11/doc/html/mp11.html[Boost.MP11
167+
https://www.boost.org/doc/libs/latest/libs/mp11/doc/html/mp11.html[Boost.MP11
166168
quoted metafunctions]. A policy is an ordinary class that contains a nested
167169
class template `fn`, which is instantiated by the registry, passing itself as
168170
the single template argument. The reason for this mechanism is to allow policies

doc/modules/ROOT/pages/shared_libraries.adoc

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,8 @@ cpp:indirect_registry[] that has the same policies as `default_registry`, plus
243243
`indirect_vptr`. Make it the registry the `BOOST_OPENMETHOD` macros use by
244244
defining
245245
xref:reference:BOOST_OPENMETHOD_DEFAULT_REGISTRY.adoc[BOOST_OPENMETHOD_DEFAULT_REGISTRY]
246-
_before_ including `<boost/openmethod.hpp>`.
246+
_before_ including `<boost/openmethod/core.hpp>`, or any header that includes
247+
it, like `<boost/openmethod.hpp>`.
247248

248249
The `indirect_vptr` example does that in the header both modules share, rather
249250
than passing a compiler switch from the build system. One place then settles
@@ -279,6 +280,9 @@ A custom registry is shared exactly the same way - name it instead of
279280
[source,c++]
280281
----
281282
// my_registry.hpp
283+
#ifndef MY_REGISTRY_DEFINED
284+
#define MY_REGISTRY_DEFINED
285+
282286
struct my_registry;
283287
#define BOOST_OPENMETHOD_DEFAULT_REGISTRY my_registry
284288
@@ -290,6 +294,8 @@ struct my_registry : boost::openmethod::registry</* policies... */> {};
290294
BOOST_OPENMETHOD_EXPORT_REGISTRY(my_registry);
291295
#else
292296
BOOST_OPENMETHOD_IMPORT_REGISTRY(my_registry);
297+
#endif
298+
293299
#endif
294300
----
295301

include/boost/openmethod/core.hpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,14 @@
3535
//!
3636
//! `BOOST_OPENMETHOD_DEFAULT_REGISTRY` can be defined by a program to change
3737
//! the default registry globally, *before* including
38-
//! `<boost/openmethod.hpp>`. After that, changing its value has no effect,
38+
//! `<boost/openmethod/core.hpp>` (or any header that includes it, like
39+
//! `<boost/openmethod.hpp>`). After that, changing its value has no effect,
3940
//! even on other macros.
4041
//!
4142
//! To use a registry that the library provides, name it in the macro:
4243
//!
4344
//! @code
44-
//! #define BOOST_OPENMETHOD_DEFAULT_REGISTRY \
45-
//! boost::openmethod::indirect_registry
45+
//! #define BOOST_OPENMETHOD_DEFAULT_REGISTRY boost::openmethod::indirect_registry
4646
//! #include <boost/openmethod.hpp>
4747
//! @endcode
4848
//!
@@ -1972,7 +1972,8 @@ struct validate_method_parameter<
19721972
//! The default value for `Registry` is @ref default_registry, but it can be
19731973
//! overridden by defining the preprocessor symbol
19741974
//! @ref BOOST_OPENMETHOD_DEFAULT_REGISTRY, *before* including
1975-
//! `<boost/openmethod.hpp>`. Setting the symbol afterwards has no effect.
1975+
//! `<boost/openmethod/core.hpp>` (or any header that includes it, like
1976+
//! `<boost/openmethod.hpp>`). Setting the symbol afterwards has no effect.
19761977
//!
19771978
//! Specializations of `method` have a single instance: the static member `fn`,
19781979
//! which has an `operator()` that forwards to the appropriate overrider. It is

include/boost/openmethod/default_registry.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,8 @@ struct indirect_registry : default_registry::with<policies::indirect_vptr> {};
8989
//! Enable runtime checks in @ref boost::openmethod::default_registry.
9090
//!
9191
//! May be defined by a program before including
92-
//! `<boost/openmethod.hpp>` to enable runtime checks. See
92+
//! `<boost/openmethod/default_registry.hpp>` (or any header that includes it,
93+
//! like `<boost/openmethod.hpp>`) to enable runtime checks. See
9394
//! @ref boost::openmethod::default_registry for details.
9495
//!
9596
//! @par Example

include/boost/openmethod/macros.hpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -177,8 +177,9 @@ inline constexpr bool method_not_found = false;
177177
//!
178178
//! @note The default registry is the value of
179179
//! @ref BOOST_OPENMETHOD_DEFAULT_REGISTRY at the point
180-
//! `<boost/openmethod.hpp>` is included. Changing the value of this symbol
181-
//! has no effect after that point.
180+
//! `<boost/openmethod/core.hpp>` is included, directly or through a header
181+
//! like `<boost/openmethod.hpp>`. Changing the value of this symbol has no
182+
//! effect after that point.
182183
//!
183184
//! @par Example
184185
//!
@@ -536,8 +537,9 @@ inline constexpr bool method_not_found = false;
536537
//! documentation for more details.
537538
//!
538539
//! @note The default registry is the value of
539-
//! @ref BOOST_OPENMETHOD_DEFAULT_REGISTRY when `<boost/openmethod.hpp>` is
540-
//! included. Subsequently changing it has no retroactive effect.
540+
//! @ref BOOST_OPENMETHOD_DEFAULT_REGISTRY when `<boost/openmethod/core.hpp>`
541+
//! is included, directly or through a header like `<boost/openmethod.hpp>`.
542+
//! Subsequently changing it has no retroactive effect.
541543
//!
542544
//! @par Examples
543545
//!

0 commit comments

Comments
 (0)