Skip to content

Commit 1e75b03

Browse files
committed
add CLAUDE.md
1 parent d096201 commit 1e75b03

File tree

1 file changed

+299
-0
lines changed

1 file changed

+299
-0
lines changed

CLAUDE.md

Lines changed: 299 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,299 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## Project Overview
6+
7+
Boost.OpenMethod is a C++17 header-only library implementing open multi-methods (multiple dispatch). Unlike traditional virtual functions where dispatch occurs only on the first (`this`) parameter, open methods dispatch based on the runtime types of multiple arguments.
8+
9+
**Key Characteristics:**
10+
- C++17 required
11+
- Header-only library
12+
- Part of the Boost ecosystem
13+
- Supports both CMake and Boost.Build (b2)
14+
15+
## Build System
16+
17+
### CMake Build
18+
19+
**Basic build:**
20+
```bash
21+
mkdir build && cd build
22+
cmake .. -DBOOST_SRC_DIR=/path/to/boost
23+
cmake --build .
24+
```
25+
26+
**Build with tests:**
27+
```bash
28+
cmake .. -DBOOST_OPENMETHOD_BUILD_TESTS=ON
29+
cmake --build . --target tests
30+
ctest
31+
```
32+
33+
**Build with examples:**
34+
```bash
35+
cmake .. -DBOOST_OPENMETHOD_BUILD_TESTS=ON -DBOOST_OPENMETHOD_BUILD_EXAMPLES=ON
36+
cmake --build .
37+
```
38+
39+
**Important CMake options:**
40+
- `BOOST_OPENMETHOD_BUILD_TESTS` - Enable tests (default: ON if root project)
41+
- `BOOST_OPENMETHOD_BUILD_EXAMPLES` - Enable examples (requires tests enabled)
42+
- `BOOST_OPENMETHOD_WARNINGS_AS_ERRORS` - Treat warnings as errors
43+
- `BOOST_SRC_DIR` - Path to Boost source directory (default: `../..` or `$BOOST_SRC_DIR` env var)
44+
45+
### Boost.Build (b2)
46+
47+
**Build and test:**
48+
```bash
49+
b2 test
50+
```
51+
52+
**Quick test (for CI):**
53+
```bash
54+
b2 test//quick
55+
```
56+
57+
## Testing
58+
59+
### Running All Tests (CMake)
60+
```bash
61+
cd build
62+
ctest
63+
```
64+
65+
### Running a Single Test (CMake)
66+
```bash
67+
cd build
68+
ctest -R test_dispatch # Run specific test by name
69+
# or directly
70+
./boost_openmethod-test_dispatch
71+
```
72+
73+
### Test Structure
74+
- Test files: `test/test_*.cpp` - Standard unit tests using Boost.Test
75+
- Compile-fail tests: `test/compile_fail_*.cpp` - Tests that should fail to compile
76+
- Mixed build test: `test/mix_release_debug/` - Tests mixing debug/release builds
77+
- 21+ test files covering dispatch, policies, virtual_ptr, RTTI, errors, etc.
78+
79+
### Debug Mode Features
80+
When building in Debug mode (`CMAKE_BUILD_TYPE=Debug`), runtime checks are automatically enabled via `BOOST_OPENMETHOD_ENABLE_RUNTIME_CHECKS`.
81+
82+
## Architecture
83+
84+
### Layered Design
85+
86+
The library is structured in three conceptual layers:
87+
88+
1. **Preamble Layer** ([preamble.hpp](include/boost/openmethod/preamble.hpp))
89+
- Foundational types: `type_id`, `vptr_type`, `virtual_<T>`
90+
- Registry and policy framework
91+
- Error types: `not_initialized`, `bad_call`, `no_overrider`, `ambiguous_call`, etc.
92+
- No executable dispatch code
93+
94+
2. **Core API** ([core.hpp](include/boost/openmethod/core.hpp))
95+
- `method<Id, ReturnType(Parameters...), Registry>` - Method implementation
96+
- `virtual_ptr<Class, Registry>` - "Wide pointer" combining object pointer + v-table pointer
97+
- Dispatch algorithms: `resolve_uni()` (single dispatch), `resolve_multi_*()` (multiple dispatch)
98+
- Override registration via `override_impl<>`
99+
- Class registration via `use_classes<>`
100+
101+
3. **Macro Layer** ([macros.hpp](include/boost/openmethod/macros.hpp))
102+
- `BOOST_OPENMETHOD(name, params, return_type)` - Declare method
103+
- `BOOST_OPENMETHOD_OVERRIDE(name, params, return_type)` - Declare overrider
104+
- `BOOST_OPENMETHOD_CLASSES(classes...)` - Register class hierarchy
105+
- Generates static registrar objects for automatic registration
106+
107+
### Key Concepts
108+
109+
**Open Methods**: Functions where dispatch depends on runtime types of multiple parameters, not just the first.
110+
111+
**Virtual Parameters**: Parameters marked with `virtual_<T>` or `virtual_ptr<T>` that participate in dispatch.
112+
113+
**Registries**: Template-parameterized contexts holding classes, methods, and policies. Default: `boost::openmethod::default_registry`.
114+
115+
**Policies**: Pluggable components controlling behavior:
116+
- `rtti` - Type identification (std_rtti, static_rtti, custom)
117+
- `vptr` - V-table storage (vptr_vector, vptr_map)
118+
- `type_hash` - Type ID hashing (fast_perfect_hash with hash_fn function object)
119+
- `error_handler` - Error handling strategy (default_error_handler, throw_error_handler)
120+
- `output` - Diagnostic output destination (stderr_output)
121+
- `attributes` - Visibility/DLL decoration (dllexport, dllimport, local)
122+
123+
**Dispatch Mechanisms**:
124+
- Single dispatch: Direct v-table lookup `vtbl[slot]`
125+
- Multi-dispatch: Stride-based indexing through multi-dimensional dispatch tables
126+
127+
**virtual_ptr**: A "wide pointer" combining object pointer with v-table pointer
128+
for efficient dispatch. Key for enabling dispatch on non-polymorphic or smart
129+
pointer types.
130+
131+
### Component Interaction
132+
133+
```
134+
User Code → Macros → Core API → Preamble → Policies
135+
136+
Static Registration
137+
```
138+
139+
Static initializers generated by macros call core API functions to register
140+
classes, methods, and overriders. The `initialize()` function builds dispatch
141+
tables before first use.
142+
143+
## Code Conventions
144+
145+
### Formatting
146+
The project uses clang-format with an LLVM-based style:
147+
- `AlignAfterOpenBracket: AlwaysBreak`
148+
- `AllowShortFunctionsOnASingleLine: false`
149+
- No short blocks, if statements, or loops on single lines
150+
151+
### Compiler Requirements
152+
Tests require these C++17 features (checked by Boost.Build):
153+
- auto nontype template params
154+
- deduction guides
155+
- fold expressions
156+
- if constexpr
157+
- inline variables
158+
- structured bindings
159+
- `<charconv>`, `<string_view>`, `<variant>` headers
160+
161+
## Common Development Patterns
162+
163+
### Working with Shared Libraries / DLL Support
164+
165+
**Overview**: The library supports shared library usage on Windows with proper dllexport/dllimport decoration.
166+
167+
**Key Pattern - Decoratable Static Variables**:
168+
All policy static variables use `BOOST_OPENMETHOD_DETAIL_MAKE_SYMBOL_WITH_ATTRIBUTES(name)` macro to enable DLL decoration. This generates three specializations of `global_state_<name>`:
169+
- Default (no attributes)
170+
- `__declspec(dllexport)` when registry has dllexport attributes
171+
- `__declspec(dllimport)` when registry has dllimport attributes
172+
173+
**Affected Policies**:
174+
- `stderr_output::fn::os` - Output stream (via `global_state_os`)
175+
- `default_error_handler::fn::handler` - Error handler function (via `global_state_handler`)
176+
- `fast_perfect_hash::fn::hash_fn` - Hash factors struct (via `global_state_hash_fn`)
177+
- `vptr_map::fn::vptrs` - V-table pointer map (via `global_state_vptrs`)
178+
- `vptr_vector::fn::vptr_vector_vptrs` / `vptr_vector_indirect_vptrs` - V-table vectors
179+
180+
**Example Usage**:
181+
```cpp
182+
// In header shared between library and client
183+
#ifdef LIBRARY_NAME
184+
#define MY_API boost::openmethod::declspec::dllexport
185+
#else
186+
#define MY_API boost::openmethod::declspec::dllimport
187+
#endif
188+
189+
namespace boost::openmethod {
190+
MY_API boost_openmethod_attributes(default_registry_attributes);
191+
}
192+
193+
BOOST_OPENMETHOD(my_method, (virtual_ptr<MyClass>), void, MY_API);
194+
```
195+
196+
See `doc/modules/ROOT/examples/shared_libs/` for complete examples.
197+
198+
### Custom RTTI
199+
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/`.
200+
201+
### Multiple Registries
202+
Registries are completely independent. Use separate registries to:
203+
- Isolate method sets
204+
- Apply different policies to different method families
205+
- Enable coexistence of incompatible configurations
206+
207+
Registry type must be specified consistently across related methods and classes.
208+
209+
## File Organization
210+
211+
- `include/boost/openmethod/` - Public headers
212+
- `core.hpp`, `macros.hpp`, `preamble.hpp` - Main headers
213+
- `initialize.hpp` - Dispatch table construction
214+
- `default_registry.hpp` - Default policy configuration
215+
- `detail/` - Internal implementation details
216+
- `policies/` - Policy implementations
217+
- `interop/` - Interoperability with other systems
218+
- `test/` - Unit tests and compile-fail tests
219+
- `doc/modules/ROOT/examples/` - Example programs
220+
- `doc/modules/ROOT/pages/` - AsciiDoc documentation
221+
222+
## Dependencies (Boost Libraries)
223+
224+
Required:
225+
- Boost.Assert
226+
- Boost.Config
227+
- Boost.Core
228+
- Boost.DynamicBitset
229+
- Boost.MP11 (metaprogramming)
230+
- Boost.Preprocessor
231+
232+
For testing:
233+
- Boost.Test
234+
- Boost.SmartPtr
235+
236+
For examples:
237+
- Boost.DLL (shared library examples)
238+
239+
## Development Workflow
240+
241+
1. Make changes to headers in `include/boost/openmethod/`
242+
2. Build tests: `cmake --build build --target tests`
243+
3. Run tests: `cd build && ctest`
244+
4. For changes affecting examples: enable `BOOST_OPENMETHOD_BUILD_EXAMPLES`
245+
5. Submit PRs against the `develop` branch
246+
247+
## Important Implementation Details
248+
249+
### Static Registration
250+
Classes, methods, and overriders register automatically via static constructors. This happens before `main()`. The `initialize()` function must be called before first method invocation to build dispatch tables.
251+
252+
### Dispatch Table Construction
253+
The `initialize()` function:
254+
1. Collects registered classes and overriders
255+
2. Builds class hierarchy using provided inheritance relationships
256+
3. Constructs dispatch tables using perfect hashing
257+
4. Validates configuration (in debug mode or with runtime_checks policy)
258+
259+
### Virtual Pointer Mechanics
260+
`virtual_ptr<T>` stores both object pointer and v-table pointer. It can be constructed from:
261+
- Raw pointers (requires prior `use_classes` registration)
262+
- Smart pointers (std::unique_ptr, std::shared_ptr, boost::intrusive_ptr)
263+
- References
264+
- Other virtual_ptr instances
265+
266+
The v-table pointer enables O(1) method dispatch.
267+
268+
### Policy Static Variables Pattern
269+
270+
When adding static variables to policies:
271+
272+
1. **Declare the variable storage** in `detail` namespace using `BOOST_OPENMETHOD_DETAIL_MAKE_SYMBOL_WITH_ATTRIBUTES(variable_name)`
273+
2. **Use type alias** in policy's `fn<Registry>` class: `using var_storage = detail::global_state_variable_name<Type, Registry>`
274+
3. **Access via storage**: `var_storage::variable_name` instead of direct static member
275+
4. **Define specialization** outside class: `template<class Registry> Type detail::global_state_variable_name<Type, Registry>::variable_name;`
276+
277+
This pattern ensures static variables can be properly decorated with dllexport/dllimport for shared library usage.
278+
279+
**Example from fast_perfect_hash**:
280+
```cpp
281+
// In detail namespace
282+
struct hash_fn {
283+
std::size_t mult, shift, min_value, max_value;
284+
auto operator()(type_id type) const -> std::size_t {
285+
return (mult * reinterpret_cast<uintptr>(type)) >> shift;
286+
}
287+
};
288+
BOOST_OPENMETHOD_DETAIL_MAKE_SYMBOL_WITH_ATTRIBUTES(hash_fn);
289+
290+
// In policy
291+
template<class Registry>
292+
class fn {
293+
using factors_storage = detail::global_state_hash_fn<detail::hash_fn, Registry>;
294+
public:
295+
static auto hash(type_id type) -> std::size_t {
296+
return factors_storage::hash_fn(type); // Use via storage
297+
}
298+
};
299+
```

0 commit comments

Comments
 (0)