Skip to content

Commit a0e1c8a

Browse files
jll63claude
andcommitted
Refactor initialize.hpp: de-template compiler to fix 32-bit MSVC C1060
Move the policy-independent dispatch-table-construction algorithm (~1300 lines) from the doubly-nested template registry<Policies...>::compiler<Options...> into the non-template detail::generic_compiler, so it compiles once per TU instead of once per distinct registry type. This fixes the 32-bit MSVC (cl.exe, ~2GB VA space) C1060 "compiler out of heap space" error when test_compiler.cpp etc. defined multiple registries. Key changes: - Add abstract trace_sink with per-registry trace_sink_impl<Registry> virtual overrides (5 small virtuals per registry instead of hundreds of operator<< instantiations). - Move all algorithm member functions to detail::generic_compiler (now non- template): build_class_lattice, assign_slots, build_dispatch_tables, etc. Replace if constexpr(has_trace) with if(tr.on()) and has_option<n2216> with use_n2216. - Reduce registry<...>::compiler<> to a thin shim: resolve_classes, resolve_methods, ctor binding tr.sink to the concrete sink impl, and install_global_tables running policies then swapping dispatch_data into registry::state. - All changes confined to initialize.hpp. Remove test/Jamfile's <toolset>msvc-14.5,<address-model>32:<build>no skip now that 32-bit works. - Add trace_demo.cpp example: demonstrates dispatch/next/tracing with BOOST_OPENMETHOD_TRACE=1. Verified: MSVC 14.5 x86_64 full suite pass; MSVC 14.5 x86_32 full suite pass (C1060 gone); gcc 13.4 -Werror clean; trace output identical (byte-for-byte after address normalization). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 6c68414 commit a0e1c8a

3 files changed

Lines changed: 812 additions & 648 deletions

File tree

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
// Copyright (c) 2018-2025 Jean-Louis Leroy
2+
// Distributed under the Boost Software License, Version 1.0.
3+
// See accompanying file LICENSE_1_0.txt
4+
// or copy at http://www.boost.org/LICENSE_1_0.txt)
5+
6+
// Demonstrates tracing the construction of the dispatch tables. The example
7+
// exercises single dispatch, `next`, and multiple dispatch. Run it with the
8+
// environment variable BOOST_OPENMETHOD_TRACE=1 to print a detailed trace of
9+
// the inheritance lattice, slot allocation, dispatch tables and `next` links
10+
// to stderr.
11+
12+
#include <iostream>
13+
#include <memory>
14+
15+
#include <boost/openmethod.hpp>
16+
#include <boost/openmethod/initialize.hpp>
17+
18+
using boost::openmethod::virtual_ptr;
19+
20+
struct Animal {
21+
virtual ~Animal() = default;
22+
};
23+
struct Dog : Animal {};
24+
struct Cat : Animal {};
25+
struct Bulldog : Dog {};
26+
27+
BOOST_OPENMETHOD_CLASSES(Animal, Dog, Cat, Bulldog);
28+
29+
// Single dispatch, with an overrider that calls `next`.
30+
BOOST_OPENMETHOD(poke, (std::ostream&, virtual_ptr<Animal>), void);
31+
32+
BOOST_OPENMETHOD_OVERRIDE(poke, (std::ostream & os, virtual_ptr<Dog>), void) {
33+
os << "growls";
34+
}
35+
36+
BOOST_OPENMETHOD_OVERRIDE(
37+
poke, (std::ostream & os, virtual_ptr<Bulldog> dog), void) {
38+
next(os, dog); // -> the Dog overrider
39+
os << " and bites";
40+
}
41+
42+
// Multiple dispatch.
43+
BOOST_OPENMETHOD(
44+
meet, (std::ostream&, virtual_ptr<Animal>, virtual_ptr<Animal>), void);
45+
46+
BOOST_OPENMETHOD_OVERRIDE(
47+
meet, (std::ostream & os, virtual_ptr<Animal>, virtual_ptr<Animal>), void) {
48+
os << "ignore each other";
49+
}
50+
51+
BOOST_OPENMETHOD_OVERRIDE(
52+
meet, (std::ostream & os, virtual_ptr<Dog>, virtual_ptr<Cat>), void) {
53+
os << "the dog chases the cat";
54+
}
55+
56+
BOOST_OPENMETHOD_OVERRIDE(
57+
meet, (std::ostream & os, virtual_ptr<Cat>, virtual_ptr<Dog>), void) {
58+
os << "the cat flees the dog";
59+
}
60+
61+
auto main() -> int {
62+
namespace bom = boost::openmethod;
63+
64+
// `trace::from_env()` enables tracing when BOOST_OPENMETHOD_TRACE=1 is set.
65+
// Pass `bom::trace(true)` instead to force tracing on unconditionally.
66+
bom::initialize(bom::trace::from_env());
67+
68+
std::unique_ptr<Animal> hector = std::make_unique<Bulldog>();
69+
std::unique_ptr<Animal> felix = std::make_unique<Cat>();
70+
71+
poke(std::cout, *hector); // growls and bites
72+
std::cout << ".\n";
73+
74+
meet(std::cout, *hector, *felix); // the dog chases the cat
75+
std::cout << ".\n";
76+
77+
return 0;
78+
}

0 commit comments

Comments
 (0)