From 4244d495416e74a9d0e05b4f648f47894241dd1b Mon Sep 17 00:00:00 2001 From: Jean-Louis Leroy Date: Sat, 17 Oct 2026 13:17:20 -0400 Subject: [PATCH 01/11] doc: link the motivation example to Compiler Explorer dev/ce_link.py turns the tagged region of a doc example into a godbolt.org/clientstate URL that carries the source itself, so nothing is stored on Compiler Explorer until a reader opens the link, and the link is regenerated from the example when the example changes. Co-Authored-By: Claude Opus 5.5 --- dev/ce_link.py | 76 ++++++++++++++++++++++++++ doc/modules/ROOT/pages/motivation.adoc | 2 + 2 files changed, 78 insertions(+) create mode 100755 dev/ce_link.py diff --git a/dev/ce_link.py b/dev/ce_link.py new file mode 100755 index 000000000..d4cf9e58a --- /dev/null +++ b/dev/ce_link.py @@ -0,0 +1,76 @@ +#!/usr/bin/env python3 +# Copyright (c) 2017-2026 Jean-Louis Leroy +# Distributed under the Boost Software License, Version 1.0. +# See accompanying file LICENSE_1_0.txt +# or copy at http://www.boost.org/LICENSE_1_0.txt) + +"""Print a Compiler Explorer link that opens a documentation example. + +The link carries the source itself, as a `/clientstate/` URL: nothing +is stored on Compiler Explorer until a reader opens it, and the link is +regenerated from the example whenever the example changes: + + dev/ce_link.py doc/modules/ROOT/examples/ast_virtual_function.cpp + +The source is the tagged region the page includes - `tag=content` by default - +so the reader gets exactly the code shown above the link. +""" + +import argparse +import base64 +import json +import sys +import urllib.parse +import zlib +from pathlib import Path + +COMPILER = "g162" # x86-64 gcc 16.2 +OPTIONS = "-std=c++17 -O2" + + +def tagged_region(path, tag): + begin, end = f"// tag::{tag}[]", f"// end::{tag}[]" + lines = path.read_text().splitlines(keepends=True) + starts = [i for i, line in enumerate(lines) if line.strip() == begin] + ends = [i for i, line in enumerate(lines) if line.strip() == end] + + if len(starts) != 1 or len(ends) != 1 or starts[0] > ends[0]: + sys.exit(f"{path}: expected exactly one `{begin}` ... `{end}`") + + return "".join(lines[starts[0] + 1 : ends[0]]) + + +def clientstate_url(source): + state = { + "sessions": [ + { + "id": 1, + "language": "c++", + "source": source, + "compilers": [{"id": COMPILER, "options": OPTIONS}], + "executors": [ + {"compiler": {"id": COMPILER, "libs": [], "options": OPTIONS}} + ], + } + ] + } + # CE detects the deflate on its own. + packed = zlib.compress(json.dumps(state).encode(), 9) + encoded = base64.b64encode(packed).decode() + # Escape `+`, `/` and `=`: a pair of `+` would be taken by AsciiDoc for a + # passthrough before the `link:` macro sees the URL. + encoded = urllib.parse.quote(encoded, safe="") + + return "https://godbolt.org/clientstate/" + encoded + + +def main(): + parser = argparse.ArgumentParser(description=__doc__.splitlines()[0]) + parser.add_argument("example", type=Path) + parser.add_argument("--tag", default="content") + args = parser.parse_args() + print(clientstate_url(tagged_region(args.example, args.tag))) + + +if __name__ == "__main__": + main() diff --git a/doc/modules/ROOT/pages/motivation.adoc b/doc/modules/ROOT/pages/motivation.adoc index 895f7dd67..a67c3db14 100644 --- a/doc/modules/ROOT/pages/motivation.adoc +++ b/doc/modules/ROOT/pages/motivation.adoc @@ -9,6 +9,8 @@ expressions: include::{examplesdir}/ast_virtual_function.cpp[tag=content] ---- +link:https://godbolt.org/clientstate/eNrFU2FLwzAQ%2FStHBOlc57YqCu3mT1A%2FiF%2FsPmRprIE0GWlShFB%2Fu5etHV0HgiDYQpt79%2FLuXZvzpOZ1LbSqSQpvnogC38sYiKSqdLTkGBI2nRKEau0M2wMXQjHpCg4roWtrOK0ecpUrXDpm4VFjxucK8GqEsY5K%2BApgNAHfnuJCWWiodCHH0IWFNSyyXLXZQPCVGkG3kkN6ot3D0VFkgowm6pZ9qfMSuuHGiCAEhltnFDQZDNljA8%2FS1aPiAYoOcgG%2BBMnfbQxDxIjywwZLIRWFxyQ%2BgFGX%2Bo3FsP%2B6J00POn18dD82lJ0bGvf2Iio%2Bbm6P%2FV93V3%2FQXShaUaHCmTs9LkB90saw9Tf4ZP428Ps%2FCoWnmGqz7rNwXyCnZ9S2SFOmnYXVCvjRLgY5ybEoyWA%2Bh2SBHnIVJobpaickN8PhIuXyLglJvbPd3JEZKq9xypb3MHtKSLvBNP%2FkzFnd7%2B2lMBoLSbHdkzY%2Fi7YbvL8BAphHLw%3D%3D[Run this example on Compiler Explorer^] + We want to add a new operation that prints the expression in postfix notation. How do we do it? From acebb83ff8929e55d8af4d2e7f02d8b50afca8c4 Mon Sep 17 00:00:00 2001 From: Jean-Louis Leroy Date: Sat, 17 Oct 2026 13:24:46 -0400 Subject: [PATCH 02/11] doc: link "Putting it all together" to a Compiler Explorer diff dev/ce_link.py --base opens the example beside another one, with CE's source diff between the two and the example's output: here, the open-method AST against the virtual function version from the motivation page. An example that includes a Boost header gets Boost 1.92 from CE's library list. The tag directives nested in the region are dropped, as Asciidoctor drops them from the include. Co-Authored-By: Claude Opus 5.5 --- dev/ce_link.py | 95 ++++++++++++++++++++++++-- doc/modules/ROOT/pages/basics.adoc | 2 + doc/modules/ROOT/pages/motivation.adoc | 2 +- 3 files changed, 91 insertions(+), 8 deletions(-) diff --git a/dev/ce_link.py b/dev/ce_link.py index d4cf9e58a..a92ceeca0 100755 --- a/dev/ce_link.py +++ b/dev/ce_link.py @@ -14,11 +14,22 @@ The source is the tagged region the page includes - `tag=content` by default - so the reader gets exactly the code shown above the link. + +With `--base`, the link opens a diff instead: the base example in editor #1, +the example in editor #2, the source diff between them, and the example's +output. + + dev/ce_link.py doc/modules/ROOT/examples/ast.cpp \\ + --base doc/modules/ROOT/examples/ast_virtual_function.cpp + +An example that includes a Boost header gets the Boost release that Compiler +Explorer offers in its Libraries dropdown, not the headers of this tree. """ import argparse import base64 import json +import re import sys import urllib.parse import zlib @@ -26,6 +37,8 @@ COMPILER = "g162" # x86-64 gcc 16.2 OPTIONS = "-std=c++17 -O2" +BOOST = "192" # Boost 1.92.0, as Compiler Explorer names it +TAG_DIRECTIVE = re.compile(r"\s*// (tag|end)::\w+\[\]\s*$") def tagged_region(path, tag): @@ -37,23 +50,83 @@ def tagged_region(path, tag): if len(starts) != 1 or len(ends) != 1 or starts[0] > ends[0]: sys.exit(f"{path}: expected exactly one `{begin}` ... `{end}`") - return "".join(lines[starts[0] + 1 : ends[0]]) + # Like Asciidoctor, drop the directives of the tags nested in the region. + region = lines[starts[0] + 1 : ends[0]] + + return "".join(line for line in region if not TAG_DIRECTIVE.match(line)) + + +def uses_boost(source): + return "#include Date: Sat, 17 Oct 2026 13:28:49 -0400 Subject: [PATCH 03/11] doc: link the postfix virtual function version, diff the disassembly The motivation link moves to the listing that adds `postfix` as a virtual function, and opens the complete program, ast_virtual_function_2.cpp. The "Putting it all together" diff now takes that program as its base, and compiles both sides so that it also shows the diff between their disassemblies (Intel syntax). Co-Authored-By: Claude Opus 5.5 --- dev/ce_link.py | 80 +++++++++++++++++++------- doc/modules/ROOT/pages/basics.adoc | 2 +- doc/modules/ROOT/pages/motivation.adoc | 4 +- 3 files changed, 61 insertions(+), 25 deletions(-) diff --git a/dev/ce_link.py b/dev/ce_link.py index a92ceeca0..f97249bd4 100755 --- a/dev/ce_link.py +++ b/dev/ce_link.py @@ -16,11 +16,11 @@ so the reader gets exactly the code shown above the link. With `--base`, the link opens a diff instead: the base example in editor #1, -the example in editor #2, the source diff between them, and the example's -output. +the example in editor #2, the diffs between their sources and between their +disassemblies, and the example's output. dev/ce_link.py doc/modules/ROOT/examples/ast.cpp \\ - --base doc/modules/ROOT/examples/ast_virtual_function.cpp + --base doc/modules/ROOT/examples/ast_virtual_function_2.cpp --base-tag all An example that includes a Boost header gets the Boost release that Compiler Explorer offers in its Libraries dropdown, not the headers of this tree. @@ -38,6 +38,14 @@ COMPILER = "g162" # x86-64 gcc 16.2 OPTIONS = "-std=c++17 -O2" BOOST = "192" # Boost 1.92.0, as Compiler Explorer names it +FILTERS = { + "intel": True, + "demangle": True, + "labels": True, + "libraryCode": True, + "directives": True, + "commentOnly": True, +} TAG_DIRECTIVE = re.compile(r"\s*// (tag|end)::\w+\[\]\s*$") @@ -82,10 +90,28 @@ def component(name, **state): def diff_state(base, source): + def libs(source): + return [{"name": "boost", "ver": BOOST}] if uses_boost(source) else [] + def editor(id, source): return component("codeEditor", id=id, lang="c++", source=source) - libs = [{"name": "boost", "ver": BOOST}] if uses_boost(source) else [] + def compiler(id, source): + return component( + "compiler", + id=id, + source=id, + lang="c++", + compiler=COMPILER, + libs=libs(source), + options=OPTIONS, + filters=FILTERS, + ) + + def diff(lhs, rhs, difftype): + return component( + "diff", lhs=lhs, rhs=rhs, lhsdifftype=difftype, rhsdifftype=difftype + ) return { "content": [ @@ -101,25 +127,33 @@ def editor(id, source): "activeItemIndex": 1, "content": [editor(1, base), editor(2, source)], }, - component( - "executor", - source=2, - lang="c++", - compiler=COMPILER, - libs=libs, - options=OPTIONS, - compilationPanelShown=True, - compilerOutShown=True, - ), + { + "type": "stack", + "activeItemIndex": 2, + "content": [ + compiler(1, base), + compiler(2, source), + component( + "executor", + source=2, + lang="c++", + compiler=COMPILER, + libs=libs(source), + options=OPTIONS, + compilationPanelShown=True, + compilerOutShown=True, + ), + ], + }, + ], + }, + { + "type": "column", + "content": [ + diff("source_1", "source_2", 16), # DiffType.Source + diff(1, 2, 0), # DiffType.ASM ], }, - component( - "diff", - lhs="source_1", - rhs="source_2", - lhsdifftype=16, # DiffType.Source - rhsdifftype=16, - ), ], } ] @@ -142,11 +176,13 @@ def main(): parser.add_argument("example", type=Path) parser.add_argument("--tag", default="content") parser.add_argument("--base", type=Path, help="open a diff against this example") + parser.add_argument("--base-tag", help="the tag of the base (default: --tag)") args = parser.parse_args() source = tagged_region(args.example, args.tag) if args.base: - state = diff_state(tagged_region(args.base, args.tag), source) + base = tagged_region(args.base, args.base_tag or args.tag) + state = diff_state(base, source) else: state = session_state(source) diff --git a/doc/modules/ROOT/pages/basics.adoc b/doc/modules/ROOT/pages/basics.adoc index 994ac92e1..50852e8ac 100644 --- a/doc/modules/ROOT/pages/basics.adoc +++ b/doc/modules/ROOT/pages/basics.adoc @@ -114,7 +114,7 @@ Putting it all together: include::{examplesdir}/ast.cpp[tag=content] ---- -link:https://godbolt.org/clientstate/eNrtV21P2zAQ%2FiunTIIUwksLYlpLK22j0pA2iijiy8qQSQy1ltqR4wRY1P323TkJTUvbgai0fSAf3Pju8XN3se%2FOzRxfScOlcZrwPXPMQ8TxzdHqzvFgvs5XYTKSpL4TgRmiaH93ETY2zP9JUOYbkfJjw0fHMuD3qKsv5h9FSpLYq0xO2KjQBrwbCKP0lLpvmCF95oigIA%2BZvLUrNjcJGqtE%2B5binZB%2BmAQcDoWKjeZs1BnIgcTXxDdwggYgG0jAJxXaJCyE3yR0a5CNp%2BVCGkhZmJAOY4kNtGG3NZDjVoXwgmnBrkMOzSnuUuw%2BktQQkbrFa2nqqQmVcq0FEYHmJtES0hZU0bMOnIZJPGOcRG5OR%2BI1CPmN8aAq0eJ2aMglUrk01Lxc6Baql7hI67dL0GbOU84fvZ91qPXUodnYzsWIzwZnZf8uuo0VREdGR0xIOnPTxwVY1hh7cJ3t4ehn%2B4QvdxSCjKFq3Co%2BC88CxJSI2ATNpq8SA4eHwB%2FdxcnAGaBRpwU7O9DYRR8G0hkj%2FWpzsrEsJ9%2BS7y35%2Fpfkwyz4scrHMobiWjP9AJQrVtBe5WMZWRSFwmdGKDkxk67yoa8z6Z7XCtvnjoq4HHEzVMH2MIo6ywA7QgojWCh%2B8SfYqVacxELegl3ebE7WN5tF7l9FRtut%2BtTr9c%2Bveqfdk2%2Fd8y%2B9IzfCJTfi3gO3Aj2c7HUHJI5eXgwLk2ugYjyAqRJBbS7rVe%2Bie3Z2fNR188O0zEhZWTp4bvViO2W6qJgKMEK3OrZ0vNY81ZYORDj%2B3XbB4xJ6q5OnKaJaVc%2FWYb01D20z5il84MAmNpIVBGLrSAcM%2FTw%2FFAt%2FfiwFfHEwG0uC%2Bfz1Y7%2Ff7bsn9kCV%2B%2B7ZLfBy%2F2sLmvmckz1JDbf04vUtv4yzPPDU%2FWvzrgMYapuGpTcD2MPmsY8ltl25JVy%2B4J7A77mfLL4lPN4G5twUCC5Crkl0Wz9okAxLapz%2FdZCFAftdSZXmyPqHhjO%2BxLmKqCoS2tnCwNvIWn8PW73GhNvWzVMmedgfqjuJUGxyvGK6l5iq5mWhB%2BLmZkHY4dD6lUd%2FVSeUnhLlwQ5j4iis1Q9y1JSIPLoc%2FwFawI8W[Run this example on Compiler Explorer, as a diff against the virtual function version^] +link:https://godbolt.org/clientstate/eNrdWG1v2zYQ%2FiuEBrRyoiS2GrSYFRvYWgMN0MVBHfTLnAa0RMfEKEqgKCWpoP32HinKlvyWOnGRrfpAU3cP7%2BUheaScW37EJeHS6qK%2Fc0s%2BxAR6lojuLAet1%2FkRS0Ou1Hc0kDMQnbY3YROJ%2FX8UFPuSZuRckvCcB%2BQedJ3N9sM44krs1F4ucGi0ARkEVEaioR5JLJU%2Bt2hgjDPMb%2FWIw0MFTaJU%2BNrEb5T7LA0IOqNRIgXBYX%2FMxxy6qS%2FRBThA%2BZgjeDIqZIoZ%2BlcJ7RbKi6accokyzFKlg1wSiXqo7TUxWUQDFIOjKb23Exl0u8bpKxQlzWGFV4vjCxYUTxhB3UZIldie%2B24BIrNNt4pwNbIoI0JQZQgJIlPBUeah4gmx1gxFCTo7q9nRXpcTuWRpspSEEtmlNSV%2BhRiZSgfVJYLezqRKTals1bScUmgb1S6pqvHHFeiwtFO9L1jYLftykHq09WogQD1DzGv02jO%2B1mjHFjocW2a1mBCWOfFWOVmm94qGZJlfLXs5gg%2F%2BMwQfPIdglXeIKVcbv7n5EM7dwkGT%2FA20fn5aeIt1jYIcg6rwzMyQPABMhSDHjfz9KJUto5oLTOw91UCXzHnV8jGEZnno5AS56A2s5VOgu4fcNkQ95lYBAe23lLrbSukea%2BaLFb%2F%2Fd9H6tSvGLtnBjvi6z0dbZHQisHhAaq9oQW%2Bfj7aI45hRH0sa8YWbbJ%2BPYmdx6ZlEUIFOopjwkMhZFBzP4ri%2FDXBCOZUUM%2FqNrGAbN6g0ofwW6eFQ2ufju12z929iKfRU%2FTkcjq5uhpeDi78GVx%2BHH2xTFB1k16Bni7nuIw6tg1YODUcfKq21Vm%2BGXwafP59%2FGNjlYtrmpKosfVi3YrOfaruYiw8WR31dOp7rXtWWPoqhfdx3dYAo9FG%2F3Kbq1KtHpg7GdWi9Y1bh86vIsxPRdaSPpPr58VQ0%2FMdzMfDNyRxsSeb9pz9Go8HIvtALqpp3R0%2BBU8bf2nD8r1nZi61hV1E8%2F5JQ5Vkt%2BJ9wS7hu3BO2fKa5T%2F1MC2PKyKMfafOrxJovtrkNEN123rpKBvU4UXFcQz%2BKVc1Ur9YR0NKDYZ136GiogVPKJBFJ6Q3CZ9CD4w8otQISgiNGFhKGJ4Qltfey6r%2BHJVIbRgXR9NSAEGIIiQ05ezDCYrcb2OMsuXWW3N1Yyi1uPOmlq1RZiez87lrFr0EiuSd%2BuvkS%2B1Lclbb1sX6JOWGjWXTHG0lr18NU1jVqZ14vJV%2F93fKEbRjQ6XQDL2ymAy%2FpuekolGiISjZmibJhvHXelqiGaJe5ejSezjwMd8V7e8V5u6TruvgOmQ4faQ%3D%3D[Run this example on Compiler Explorer, as a diff against the virtual function version^] [#registering_classes_by_reflection] diff --git a/doc/modules/ROOT/pages/motivation.adoc b/doc/modules/ROOT/pages/motivation.adoc index 8c899d910..9db7146af 100644 --- a/doc/modules/ROOT/pages/motivation.adoc +++ b/doc/modules/ROOT/pages/motivation.adoc @@ -9,8 +9,6 @@ expressions: include::{examplesdir}/ast_virtual_function.cpp[tag=content] ---- -link:https://godbolt.org/clientstate/eNrFU9FOgzAU%2FZWbmhjmmNvQaAKbn6A%2BGF9kD12p2KS0S2mJSYPf7u0GC2NPGhMhKb3nXM49F3o9qXldC61qksKbJ6LA5zIGIqkqHS05hoRNpwShWjvD9sCFUEy6gsNK6NoaTquHXOUKt45ZeNTI%2BFwBXo0w1lEJXwGMJuDbU1woCw2VLnAMXVhYwyLLVZsNBF%2BpEXQrOaQn2j0cHUUmmNFE3bYvdV5CN9wYEYTAcOuMgiaDYfbYwLN09ah4gKKDXIAvQfJ3G8MQMaL8sMFSoKKwTOIDGHXUTyyG96%2F7pOlBp4%2BP7seGsnND495eRMXHze2x%2F%2Bvu6g%2B6C0UrKlQ4c6fHBahP2hi2%2FgZX5m9Dfv9HofAUqTbrPgv3Beb0GbUt0pRpZ2G1An60i0FOcixKMpjPIVmgh1yFiWG62gnJzXC4SLm8SwIpxXaPb3Cvd7abQTLDKmucuOU9zJ4S0gaaf3LmrO51elmMfinabvD%2BBlDaSns%3D[Run this example on Compiler Explorer^] - We want to add a new operation that prints the expression in postfix notation. How do we do it? @@ -52,6 +50,8 @@ int main() { } ---- +link:https://godbolt.org/clientstate/eNrNVMtu2zAQ%2FJUFCyRy7DysBClg2v2EtoeilyoHmmJcAjRp8CEEINRv71KmHEnJJemhkQGanF3Ozo4oRuKEc9JoR1bwKxJZ4%2F9yAUQxvQtsJ3BJ%2BHxOEHImWN4Bn6TmKtQC1tI4bwXbf6l0pXEauIevBiOx0oBPI60PTMGfBBYziO0Yl9pDw1RIMY4qPGzgho5zGiNrOGChR%2FlUOF%2BvVrnoGRg33tbSgY6fzEq2VQJWI0k9XJxqzzCjKfK0V%2FhSmWmEtTIRgRU%2BWA0NhfYdWgdExsF6PeDpqk4b%2Ba6CmzSRoOLIluAzUOLRL2CIWLn77VNrKVSkYbY4gkUOvaXVtP%2BqT5ofefr1swtv6%2F64KT0de78RU2k25hzOaa71SrQiMK9IPi1ZwtQT%2BtKTqb0%2F5F5M%2Fe2w%2F2fwxYcx%2BOJfDE5975nU6cMff3zAYtkuYBtvceTxrqXP5xrqyDDU0vxmRKwxp88QV6P%2BuQl%2BlkMnIGvfpAGn4uRrh1cojVC4voYSbvEs36HdGyhvUHWl00XHzf4glbDDO5HslvdlCiq57fAHnJuDz1cnucTiG7wol5%2Fh8ltJ2hQWT4IHb3qenhZX7yRtH%2FD3F%2F4S1Xc%3D[Run this example on Compiler Explorer^] + If the classes are part of a small, self-contained program, this may be a reasonable solution. Otherwise, there are serious problems with this approach. From 37d65594da6ca7f4c8bc8660277267fbea7a032e Mon Sep 17 00:00:00 2001 From: Jean-Louis Leroy Date: Sun, 18 Oct 2026 09:54:40 -0400 Subject: [PATCH 04/11] doc: compare the postfix calls' assembly on Compiler Explorer performance.adoc gets a link that compiles the virtual function call and the two method calls side by side with clang, each in its own compiler pane. They come from two minimal translation units, dispatch_virtual_function.cpp and dispatch_open_method.cpp: a full program buries the calls under the registration code. The page now includes its three call listings from those files, so the page and the link show the same code; each file ends with an empty main, outside the tagged region, so it still builds as an example. The diff on basics.adoc drops its assembly diff, which compared whole programs, and keeps the source diff and the output. dev/ce_link.py: --beside, --compiler; --base-tag becomes --other-tag. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01958YRGfNfb6SfQS9v4hWTr --- dev/ce_link.py | 127 ++++++++++-------- .../ROOT/examples/dispatch_open_method.cpp | 35 +++++ .../examples/dispatch_virtual_function.cpp | 25 ++++ doc/modules/ROOT/pages/basics.adoc | 2 +- doc/modules/ROOT/pages/performance.adoc | 14 +- 5 files changed, 136 insertions(+), 67 deletions(-) create mode 100644 doc/modules/ROOT/examples/dispatch_open_method.cpp create mode 100644 doc/modules/ROOT/examples/dispatch_virtual_function.cpp diff --git a/dev/ce_link.py b/dev/ce_link.py index f97249bd4..f04e321ef 100755 --- a/dev/ce_link.py +++ b/dev/ce_link.py @@ -16,11 +16,18 @@ so the reader gets exactly the code shown above the link. With `--base`, the link opens a diff instead: the base example in editor #1, -the example in editor #2, the diffs between their sources and between their -disassemblies, and the example's output. +the example in editor #2, the diff between their sources, and the example's +output. dev/ce_link.py doc/modules/ROOT/examples/ast.cpp \\ - --base doc/modules/ROOT/examples/ast_virtual_function_2.cpp --base-tag all + --base doc/modules/ROOT/examples/ast_virtual_function_2.cpp --other-tag all + +With `--beside`, the two examples are compiled side by side, each in its own +compiler pane, to compare the assembly: + + dev/ce_link.py doc/modules/ROOT/examples/dispatch_open_method.cpp \\ + --beside doc/modules/ROOT/examples/dispatch_virtual_function.cpp \\ + --compiler clang2310 An example that includes a Boost header gets the Boost release that Compiler Explorer offers in its Libraries dropdown, not the headers of this tree. @@ -35,7 +42,7 @@ import zlib from pathlib import Path -COMPILER = "g162" # x86-64 gcc 16.2 +COMPILER = "g162" # x86-64 gcc 16.2; clang2310 is x86-64 clang 23.1.0 OPTIONS = "-std=c++17 -O2" BOOST = "192" # Boost 1.92.0, as Compiler Explorer names it FILTERS = { @@ -68,9 +75,9 @@ def uses_boost(source): return "#include +#include + +struct Node { + virtual ~Node() {} + virtual int value() const = 0; +}; + +using boost::openmethod::virtual_ptr; + +BOOST_OPENMETHOD(postfix, (virtual_ptr node, std::ostream& os), void); + +// tag::call_via_ref[] +void call_via_ref(const Node& node, std::ostream& os) { + postfix(node, os); +} +// end::call_via_ref[] + +// tag::call_via_virtual_ptr[] +void call_via_virtual_ptr(virtual_ptr node, std::ostream& os) { + postfix(node, os); +} +// end::call_via_virtual_ptr[] +// end::content[] + +int main() { +} diff --git a/doc/modules/ROOT/examples/dispatch_virtual_function.cpp b/doc/modules/ROOT/examples/dispatch_virtual_function.cpp new file mode 100644 index 000000000..9ba1f6b10 --- /dev/null +++ b/doc/modules/ROOT/examples/dispatch_virtual_function.cpp @@ -0,0 +1,25 @@ +// Copyright (c) 2017-2026 Jean-Louis Leroy +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +// clang-format off + +// tag::content[] +#include + +struct Node { + virtual ~Node() {} + virtual int value() const = 0; + virtual void postfix(std::ostream& os) const = 0; +}; + +// tag::call_virtual_function[] +void call_virtual_function(const Node& node, std::ostream& os) { + node.postfix(os); +} +// end::call_virtual_function[] +// end::content[] + +int main() { +} diff --git a/doc/modules/ROOT/pages/basics.adoc b/doc/modules/ROOT/pages/basics.adoc index 50852e8ac..41f705088 100644 --- a/doc/modules/ROOT/pages/basics.adoc +++ b/doc/modules/ROOT/pages/basics.adoc @@ -114,7 +114,7 @@ Putting it all together: include::{examplesdir}/ast.cpp[tag=content] ---- -link:https://godbolt.org/clientstate/eNrdWG1v2zYQ%2FiuEBrRyoiS2GrSYFRvYWgMN0MVBHfTLnAa0RMfEKEqgKCWpoP32HinKlvyWOnGRrfpAU3cP7%2BUheaScW37EJeHS6qK%2Fc0s%2BxAR6lojuLAet1%2FkRS0Ou1Hc0kDMQnbY3YROJ%2FX8UFPuSZuRckvCcB%2BQedJ3N9sM44krs1F4ucGi0ARkEVEaioR5JLJU%2Bt2hgjDPMb%2FWIw0MFTaJU%2BNrEb5T7LA0IOqNRIgXBYX%2FMxxy6qS%2FRBThA%2BZgjeDIqZIoZ%2BlcJ7RbKi6accokyzFKlg1wSiXqo7TUxWUQDFIOjKb23Exl0u8bpKxQlzWGFV4vjCxYUTxhB3UZIldie%2B24BIrNNt4pwNbIoI0JQZQgJIlPBUeah4gmx1gxFCTo7q9nRXpcTuWRpspSEEtmlNSV%2BhRiZSgfVJYLezqRKTals1bScUmgb1S6pqvHHFeiwtFO9L1jYLftykHq09WogQD1DzGv02jO%2B1mjHFjocW2a1mBCWOfFWOVmm94qGZJlfLXs5gg%2F%2BMwQfPIdglXeIKVcbv7n5EM7dwkGT%2FA20fn5aeIt1jYIcg6rwzMyQPABMhSDHjfz9KJUto5oLTOw91UCXzHnV8jGEZnno5AS56A2s5VOgu4fcNkQ95lYBAe23lLrbSukea%2BaLFb%2F%2Fd9H6tSvGLtnBjvi6z0dbZHQisHhAaq9oQW%2Bfj7aI45hRH0sa8YWbbJ%2BPYmdx6ZlEUIFOopjwkMhZFBzP4ri%2FDXBCOZUUM%2FqNrGAbN6g0ofwW6eFQ2ufju12z929iKfRU%2FTkcjq5uhpeDi78GVx%2BHH2xTFB1k16Bni7nuIw6tg1YODUcfKq21Vm%2BGXwafP59%2FGNjlYtrmpKosfVi3YrOfaruYiw8WR31dOp7rXtWWPoqhfdx3dYAo9FG%2F3Kbq1KtHpg7GdWi9Y1bh86vIsxPRdaSPpPr58VQ0%2FMdzMfDNyRxsSeb9pz9Go8HIvtALqpp3R0%2BBU8bf2nD8r1nZi61hV1E8%2F5JQ5Vkt%2BJ9wS7hu3BO2fKa5T%2F1MC2PKyKMfafOrxJovtrkNEN123rpKBvU4UXFcQz%2BKVc1Ur9YR0NKDYZ136GiogVPKJBFJ6Q3CZ9CD4w8otQISgiNGFhKGJ4Qltfey6r%2BHJVIbRgXR9NSAEGIIiQ05ezDCYrcb2OMsuXWW3N1Yyi1uPOmlq1RZiez87lrFr0EiuSd%2BuvkS%2B1Lclbb1sX6JOWGjWXTHG0lr18NU1jVqZ14vJV%2F93fKEbRjQ6XQDL2ymAy%2FpuekolGiISjZmibJhvHXelqiGaJe5ejSezjwMd8V7e8V5u6TruvgOmQ4faQ%3D%3D[Run this example on Compiler Explorer, as a diff against the virtual function version^] +link:https://godbolt.org/clientstate/eNrdV39v0zwQ%2FiqnvBKkW%2FajZQLRrJVeXioxCdaJTvxDx%2BQl3mqR2pHjZBtR%2BOz4HKdN%2BmNQVgS8%2BcNN7h7f3XO2z9fcCQRXlCunCx9zR93HVL85Utw6HqzWBSJKpxzVtyxUEy06OlyHTRQJPiOUBIpl9ETR6QkP6Z3Wtdfbn8aCo9irfZySqdWGdBAyJWRDPVJEoT53WGiNR4TfmBm7uwhNRCoDY%2BIfxoMoDSkcM5EoScm0P%2BZjrl%2FTQMGpdgD5mIN%2BMiZVSiL4ikK3BXnRlDOuICNRijrNJVHQg0O%2FickECyHWjq7ZnZuosNu1Tp%2BASJrTCr8WxwciGbmKKHQbIVVid%2Ba7pRGZa1%2BrCJcjExmVkqEhkFSlkkPmQ%2FETsdYMiQSOj2t2jNdFImdRmiyQQJFbWkPxE4jotfKgLpHsZqKQGqpcHFpeKXStahOqOH%2B%2FAu2WdqrveRY2Y19OwsdYryZqqG8T8xSe%2BtbXCu3Ygd2xY3eLDWExJ%2F5yThbTe86mdDG%2FRvb7ErzzxyR45zEJRt5Twjge%2FObhA5J3Cg%2Bu8md6DPKjwp%2FvawhzolWFb1eG5qHGVAi63%2BAfiFS1rGomsLH3cNCvdJZXIx%2Fr0BwfDg6gA8%2F0Xj7S6e5B51BHPeZOoQPabintPFRKt1gzf1vx%2B7uL1v%2B7YmzCTp%2BIT9t8jMWIXUki7wHPihH0tvkYiySOIxYQxQSfu8m2%2BWB25k3PldAV6EDElE%2BpmohwfxLH%2FYcAB4wzxUjEvtAlbKODShPGb8BM16V9Nr%2FbtWf%2FMlbSLNWr4XB0fjk8G5y%2BG5y%2FGb52bVH0wK1Bj%2Bdr3QeuRw%2BWLg3PXCqtlVYvhx8G79%2BfvB645WZ6yElVWfp638r1fqrjYhsfIvf6pnQ81j3Wlj7Eevy%2B7%2BoCQfRevzymeOvVI8OLcRXanJhl%2BKwVeTQRU0f6oPDnx6kY%2BI9zsfD1ZHYeIPPf239Ho8HIPTUbqlp3zyyBV8bfWnP9r9jZ86PhVlE8vkmoeFYb%2Fhd0CRcb9An0jgbp%2Bi5h1g2s6BQQziIqUXTTft5BmS6pSfmPj1sHJq%2Boykpk%2B2XHKS70t4ixKiLa2dPEe9pq%2BwXsDTtz26ZunhFOo9FE3HIN1Zccrbkepqqu2Yx6yK6v19COJiaukv1lG1GyISrJThK0Yb21n5eohggjuii%2BAWB8GiE%3D[Run this example on Compiler Explorer, as a diff against the virtual function version^] [#registering_classes_by_reflection] diff --git a/doc/modules/ROOT/pages/performance.adoc b/doc/modules/ROOT/pages/performance.adoc index d044c4e45..c357ff4c9 100644 --- a/doc/modules/ROOT/pages/performance.adoc +++ b/doc/modules/ROOT/pages/performance.adoc @@ -9,9 +9,7 @@ function call: [source,c++] ---- -void call_virtual_function(const Node& node, std::ostream& os) { - node.postfix(os); -} +include::{examplesdir}/dispatch_virtual_function.cpp[tag=call_virtual_function] ---- Clang compiles this function to the following assembly on the x64 architecture: @@ -29,9 +27,7 @@ Let's look at a method call now: [source,c++] ---- -void call_via_ref(const Node& node, std::ostream& os) { - postfix(node, os); -} +include::{examplesdir}/dispatch_open_method.cpp[tag=call_via_ref] ---- This compiles to (variable names are shortened for readability): @@ -86,9 +82,7 @@ If we already have a `virtual_ptr`: [source,c++] ---- -void call_via_virtual_ptr(virtual_ptr node, std::ostream& os) { - postfix(node, os); -} +include::{examplesdir}/dispatch_open_method.cpp[tag=call_via_virtual_ptr] ---- A method call compiles to: @@ -100,6 +94,8 @@ mov rax, qword ptr [rdi + 8*rax] jmp rax # TAILCALL ---- +link:https://godbolt.org/clientstate/eNrNU11r2zAU%2FSsXDYpL3a7xHsrcj4dtgb0sHrRvSwmKrbQC%2BUpIsrdgvN%2B%2BK9tJnbZb27HCEkike8791LkNyzV6gZ6l8K1hfm0EnZjV31kMj2O5VlWJf4BLozGY49FlxssBLcS0kF7bHfjScx%2FwhsmC%2FiaEKY43ncfBQaA6Xdm8C%2FFGYq6qQsCZ1M5bwcuLOc6RjlXuYUYJoJkj0KeW1ldcwc9gjPahaXftEj3UXFUBo16ch3M4Pt3l1FoWYCjRSv6InC%2FSdEi6B9rturWnoY7OIedKLYYQi1WFuZcao54citkDpN8YHgYcSg%2Fw0SYt2UP4ObK2jeH5oy6NVOLJQW8n%2B8jUtzGCKWDJu8lxAJRcuvDu13TWJnQXruyQGjon38kJHGZJIK6k8sK6PiXJRdGJXop6Z4UoKaISdxbFl0K50V0uLbfrjzSMkZu0guZZixGR6iypuwzVejC2bXt9b1ivLtvkebJdanrXt9oILIW%2F1cXRrTEk4dfXdS%2FQykm8ga4I0t62ijTd6NV42xE%2FZNnl1SL7Op19mV59zj5Fgx5jiEbUsztVX%2FxO1XG3RvsP9oMvrFi9ZC02G9HTtntxP%2BqovJeW%2BkSmf76ByVgkyV9sYMNwSNc9aYDqnj55n7D2%2F17Q8P0FOEgolQ%3D%3D[Compare the three calls on Compiler Explorer^] + `virtual_ptr` arguments are passed through the method call, to the overrider, which can use them to make further method calls. From 80043df8bee3c27c04f6952b7780dadf3fdbc729 Mon Sep 17 00:00:00 2001 From: Jean-Louis Leroy Date: Sun, 18 Oct 2026 09:59:04 -0400 Subject: [PATCH 05/11] doc: show call_via_virtual_ptr in the Compiler Explorer comparison CE's "Library functions" filter hid it: the filter goes by line info, and every instruction of call_via_virtual_ptr is dispatch code inlined from core.hpp. Turn the filter off; the call functions still come first in the clang output. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01958YRGfNfb6SfQS9v4hWTr --- dev/ce_link.py | 4 +++- doc/modules/ROOT/pages/performance.adoc | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/dev/ce_link.py b/dev/ce_link.py index f04e321ef..05484c92e 100755 --- a/dev/ce_link.py +++ b/dev/ce_link.py @@ -49,7 +49,9 @@ "intel": True, "demangle": True, "labels": True, - "libraryCode": True, + # CE takes a function whose every instruction comes from a header for + # library code: `call_via_virtual_ptr` is the inlined dispatch, all of it. + "libraryCode": False, "directives": True, "commentOnly": True, } diff --git a/doc/modules/ROOT/pages/performance.adoc b/doc/modules/ROOT/pages/performance.adoc index c357ff4c9..b345bea21 100644 --- a/doc/modules/ROOT/pages/performance.adoc +++ b/doc/modules/ROOT/pages/performance.adoc @@ -94,7 +94,7 @@ mov rax, qword ptr [rdi + 8*rax] jmp rax # TAILCALL ---- -link:https://godbolt.org/clientstate/eNrNU11r2zAU%2FSsXDYpL3a7xHsrcj4dtgb0sHrRvSwmKrbQC%2BUpIsrdgvN%2B%2BK9tJnbZb27HCEkike8791LkNyzV6gZ6l8K1hfm0EnZjV31kMj2O5VlWJf4BLozGY49FlxssBLcS0kF7bHfjScx%2FwhsmC%2FiaEKY43ncfBQaA6Xdm8C%2FFGYq6qQsCZ1M5bwcuLOc6RjlXuYUYJoJkj0KeW1ldcwc9gjPahaXftEj3UXFUBo16ch3M4Pt3l1FoWYCjRSv6InC%2FSdEi6B9rturWnoY7OIedKLYYQi1WFuZcao54citkDpN8YHgYcSg%2Fw0SYt2UP4ObK2jeH5oy6NVOLJQW8n%2B8jUtzGCKWDJu8lxAJRcuvDu13TWJnQXruyQGjon38kJHGZJIK6k8sK6PiXJRdGJXop6Z4UoKaISdxbFl0K50V0uLbfrjzSMkZu0guZZixGR6iypuwzVejC2bXt9b1ivLtvkebJdanrXt9oILIW%2F1cXRrTEk4dfXdS%2FQykm8ga4I0t62ijTd6NV42xE%2FZNnl1SL7Op19mV59zj5Fgx5jiEbUsztVX%2FxO1XG3RvsP9oMvrFi9ZC02G9HTtntxP%2BqovJeW%2BkSmf76ByVgkyV9sYMNwSNc9aYDqnj55n7D2%2F17Q8P0FOEgolQ%3D%3D[Compare the three calls on Compiler Explorer^] +link:https://godbolt.org/clientstate/eNrNU1tr2zAU%2FisHDYpL3Uu8hzL38tAusJfFg%2FZtKUGx5VYgHxlJ9haM99t3ZDup03ZrO1ZoAol0vu9c9Z2GpRqdQMdi%2BN4wtyoFnZjRP1gIT2OpVlWBf4GLUqM3h6PLjBcDmolpJp02W%2FCV487jDZMZ%2FU0IUxxvO4%2B9PU%2B1ujJpF%2BKDxFRVmYBTqa0zghfnc5wjHavUwYwSQDNHoE8tjau4gl%2FeGOxC027bJTqouao8Rr1YB2dwdLLNqbXMoKREufwZWJfF8ZB0B7TddmtPfB2dQ8qVWgwhFnmFqZMag57si9kBpN8QHgccSvfwwTot2X34ObK2DeHloy5KqcSzg95M9ompb2J4k8eij5MjDyi5tP7db%2BisS9%2Bdv7J9auiMfCfHsJ9EnphL5YSxfUqSi6ITvRT1zjJRUEQl7i2KL4Wyo7tcGm5WlzQMMuZc2c5PGkEDrcWISYUW1F6CajUY27a9eTCtN9dt9DLdLjU97KEuBRbC3ens4K4sScNvL%2BxeoZWVeAtdESS%2BTRVxvBZs6UxHvEiSq%2BtF8m06%2Bzq9%2FpJ8DgZBhhCMqKf3sj7%2Fk6zDbo92Hy0IXxiRv2Yv1ivR0zaL8TDqqLzXlvpMpv%2B%2BgtFYJNE%2FrGDDcEjXPamH6p4%2B%2BRSx9p1vqP%2F%2BBlxDKSs%3D[Compare the three calls on Compiler Explorer^] `virtual_ptr` arguments are passed through the method call, to the overrider, which can use them to make further method calls. From ba84b763b304f3e448fc33d3c946a88fce906c24 Mon Sep 17 00:00:00 2001 From: Jean-Louis Leroy Date: Sun, 18 Oct 2026 10:05:00 -0400 Subject: [PATCH 06/11] doc: performance listings from clang 23.1.0 The Compiler Explorer comparison compiles with clang 23, which folds the last load into the indirect jump: one `mov` fewer in the virtual function call and in both method calls. Update the three listings to match, and say in a note which compiler, options and Boost version they come from. llvm-mca (skylake) gives the same throughputs for the clang 23 code, 1 and 4 cycles, so the text stands. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01958YRGfNfb6SfQS9v4hWTr --- doc/modules/ROOT/pages/performance.adoc | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/doc/modules/ROOT/pages/performance.adoc b/doc/modules/ROOT/pages/performance.adoc index b345bea21..8d5dbe206 100644 --- a/doc/modules/ROOT/pages/performance.adoc +++ b/doc/modules/ROOT/pages/performance.adoc @@ -4,6 +4,11 @@ Open-methods can be as fast as ordinary virtual member functions when compiled with optimization. +NOTE: The assembly on this page is generated by x86-64 clang 23.1.0 with +`-std=c++17 -O2`, against Boost 1.92. Clang 22 and earlier load the target of +the indirect jump into a register first: one more `mov` per call, in the +virtual function call and the method calls alike. + First, let's examine the code generated by clang for an ordinary virtual function call: @@ -17,8 +22,7 @@ Clang compiles this function to the following assembly on the x64 architecture: [source,asm] ---- mov rax, qword ptr [rdi] -mov rax, qword ptr [rax + 24] -jmp rax # TAILCALL +jmp qword ptr [rax + 24] # TAILCALL ---- llvm-mca estimates this code has a throughput of 1 cycle per dispatch. @@ -44,9 +48,8 @@ This compiles to (variable names are shortened for readability): mov rcx, qword ptr [rip + vptr_vector_vptrs] mov rdi, qword ptr [rcx + 8*rdi] mov rcx, qword ptr [rip + postfix::fn+88] - mov rcx, qword ptr [rdi + 8*rcx] mov rsi, rax - jmp rcx # TAILCALL + jmp qword ptr [rdi + 8*rcx] # TAILCALL ---- This is quite a few instructions more. Upon closer examination, we see that many @@ -90,8 +93,7 @@ A method call compiles to: [source,asm] ---- mov rax, qword ptr [rip + postfix::fn+88] -mov rax, qword ptr [rdi + 8*rax] -jmp rax # TAILCALL +jmp qword ptr [rdi + 8*rax] # TAILCALL ---- link:https://godbolt.org/clientstate/eNrNU1tr2zAU%2FisHDYpL3Uu8hzL38tAusJfFg%2FZtKUGx5VYgHxlJ9haM99t3ZDup03ZrO1ZoAol0vu9c9Z2GpRqdQMdi%2BN4wtyoFnZjRP1gIT2OpVlWBf4GLUqM3h6PLjBcDmolpJp02W%2FCV487jDZMZ%2FU0IUxxvO4%2B9PU%2B1ujJpF%2BKDxFRVmYBTqa0zghfnc5wjHavUwYwSQDNHoE8tjau4gl%2FeGOxC027bJTqouao8Rr1YB2dwdLLNqbXMoKREufwZWJfF8ZB0B7TddmtPfB2dQ8qVWgwhFnmFqZMag57si9kBpN8QHgccSvfwwTot2X34ObK2DeHloy5KqcSzg95M9ompb2J4k8eij5MjDyi5tP7db%2BisS9%2Bdv7J9auiMfCfHsJ9EnphL5YSxfUqSi6ITvRT1zjJRUEQl7i2KL4Wyo7tcGm5WlzQMMuZc2c5PGkEDrcWISYUW1F6CajUY27a9eTCtN9dt9DLdLjU97KEuBRbC3ens4K4sScNvL%2BxeoZWVeAtdESS%2BTRVxvBZs6UxHvEiSq%2BtF8m06%2Bzq9%2FpJ8DgZBhhCMqKf3sj7%2Fk6zDbo92Hy0IXxiRv2Yv1ivR0zaL8TDqqLzXlvpMpv%2B%2BgtFYJNE%2FrGDDcEjXPamH6p4%2B%2BRSx9p1vqP%2F%2BBlxDKSs%3D[Compare the three calls on Compiler Explorer^] From 0948704f6d6bdee00a8751d033d524a339731bd2 Mon Sep 17 00:00:00 2001 From: Jean-Louis Leroy Date: Sun, 18 Oct 2026 10:07:07 -0400 Subject: [PATCH 07/11] doc: basics links to the open-method version alone The "Putting it all together" link now opens ast.cpp and runs it, with no diff against the virtual function version. That leaves --base without a user, so it goes; --other-tag, now used by --beside only, becomes --beside-tag. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01958YRGfNfb6SfQS9v4hWTr --- dev/ce_link.py | 61 +++--------------------------- doc/modules/ROOT/pages/basics.adoc | 2 +- 2 files changed, 6 insertions(+), 57 deletions(-) diff --git a/dev/ce_link.py b/dev/ce_link.py index 05484c92e..d319f53a5 100755 --- a/dev/ce_link.py +++ b/dev/ce_link.py @@ -15,13 +15,6 @@ The source is the tagged region the page includes - `tag=content` by default - so the reader gets exactly the code shown above the link. -With `--base`, the link opens a diff instead: the base example in editor #1, -the example in editor #2, the diff between their sources, and the example's -output. - - dev/ce_link.py doc/modules/ROOT/examples/ast.cpp \\ - --base doc/modules/ROOT/examples/ast_virtual_function_2.cpp --other-tag all - With `--beside`, the two examples are compiled side by side, each in its own compiler pane, to compare the assembly: @@ -106,46 +99,6 @@ def editor(id, source): return component("codeEditor", id=id, lang="c++", source=source) -def diff_state(base, source, compiler): - return { - "content": [ - { - "type": "row", - "content": [ - { - "type": "column", - "width": 40, - "content": [ - { - "type": "stack", - "activeItemIndex": 1, - "content": [editor(1, base), editor(2, source)], - }, - component( - "executor", - source=2, - lang="c++", - compiler=compiler, - libs=libs(source), - options=OPTIONS, - compilationPanelShown=True, - compilerOutShown=True, - ), - ], - }, - component( - "diff", - lhs="source_1", - rhs="source_2", - lhsdifftype=16, # DiffType.Source - rhsdifftype=16, - ), - ], - } - ] - } - - def beside_state(base, source, compiler): def column(id, source): return { @@ -183,21 +136,17 @@ def main(): parser = argparse.ArgumentParser(description=__doc__.splitlines()[0]) parser.add_argument("example", type=Path) parser.add_argument("--tag", default="content") - other = parser.add_mutually_exclusive_group() - other.add_argument("--base", type=Path, help="open a diff against this example") - other.add_argument( + parser.add_argument( "--beside", type=Path, help="compile this example beside, for the assembly" ) - parser.add_argument("--other-tag", help="the tag of the other example (default: --tag)") + parser.add_argument("--beside-tag", help="the tag of the other example (default: --tag)") parser.add_argument("--compiler", default=COMPILER, help="CE compiler id") args = parser.parse_args() source = tagged_region(args.example, args.tag) - other = args.base or args.beside - if other: - other = tagged_region(other, args.other_tag or args.tag) - layout = diff_state if args.base else beside_state - state = layout(other, source, args.compiler) + if args.beside: + other = tagged_region(args.beside, args.beside_tag or args.tag) + state = beside_state(other, source, args.compiler) else: state = session_state(source, args.compiler) diff --git a/doc/modules/ROOT/pages/basics.adoc b/doc/modules/ROOT/pages/basics.adoc index 41f705088..e64caf97e 100644 --- a/doc/modules/ROOT/pages/basics.adoc +++ b/doc/modules/ROOT/pages/basics.adoc @@ -114,7 +114,7 @@ Putting it all together: include::{examplesdir}/ast.cpp[tag=content] ---- -link:https://godbolt.org/clientstate/eNrdV39v0zwQ%2FiqnvBKkW%2FajZQLRrJVeXioxCdaJTvxDx%2BQl3mqR2pHjZBtR%2BOz4HKdN%2BmNQVgS8%2BcNN7h7f3XO2z9fcCQRXlCunCx9zR93HVL85Utw6HqzWBSJKpxzVtyxUEy06OlyHTRQJPiOUBIpl9ETR6QkP6Z3Wtdfbn8aCo9irfZySqdWGdBAyJWRDPVJEoT53WGiNR4TfmBm7uwhNRCoDY%2BIfxoMoDSkcM5EoScm0P%2BZjrl%2FTQMGpdgD5mIN%2BMiZVSiL4ikK3BXnRlDOuICNRijrNJVHQg0O%2FickECyHWjq7ZnZuosNu1Tp%2BASJrTCr8WxwciGbmKKHQbIVVid%2Ba7pRGZa1%2BrCJcjExmVkqEhkFSlkkPmQ%2FETsdYMiQSOj2t2jNdFImdRmiyQQJFbWkPxE4jotfKgLpHsZqKQGqpcHFpeKXStahOqOH%2B%2FAu2WdqrveRY2Y19OwsdYryZqqG8T8xSe%2BtbXCu3Ygd2xY3eLDWExJ%2F5yThbTe86mdDG%2FRvb7ErzzxyR45zEJRt5Twjge%2FObhA5J3Cg%2Bu8md6DPKjwp%2FvawhzolWFb1eG5qHGVAi63%2BAfiFS1rGomsLH3cNCvdJZXIx%2Fr0BwfDg6gA8%2F0Xj7S6e5B51BHPeZOoQPabintPFRKt1gzf1vx%2B7uL1v%2B7YmzCTp%2BIT9t8jMWIXUki7wHPihH0tvkYiySOIxYQxQSfu8m2%2BWB25k3PldAV6EDElE%2BpmohwfxLH%2FYcAB4wzxUjEvtAlbKODShPGb8BM16V9Nr%2FbtWf%2FMlbSLNWr4XB0fjk8G5y%2BG5y%2FGb52bVH0wK1Bj%2Bdr3QeuRw%2BWLg3PXCqtlVYvhx8G79%2BfvB645WZ6yElVWfp638r1fqrjYhsfIvf6pnQ81j3Wlj7Eevy%2B7%2BoCQfRevzymeOvVI8OLcRXanJhl%2BKwVeTQRU0f6oPDnx6kY%2BI9zsfD1ZHYeIPPf239Ho8HIPTUbqlp3zyyBV8bfWnP9r9jZ86PhVlE8vkmoeFYb%2Fhd0CRcb9An0jgbp%2Bi5h1g2s6BQQziIqUXTTft5BmS6pSfmPj1sHJq%2Boykpk%2B2XHKS70t4ixKiLa2dPEe9pq%2BwXsDTtz26ZunhFOo9FE3HIN1Zccrbkepqqu2Yx6yK6v19COJiaukv1lG1GyISrJThK0Yb21n5eohggjuii%2BAWB8GiE%3D[Run this example on Compiler Explorer, as a diff against the virtual function version^] +link:https://godbolt.org/clientstate/eNrFVn9r2zAQ%2FSqHB63SOE2Tlo3FiWFbAxtsTWlC%2F1m6othqKnAkI8umm%2FE%2B%2B06ynZ9t17GMKUS2n57u3Vmnk3MnYUnCpUicHnzNHR7iteOCE1ExT%2Bmc4aMTNJsOQolMVWCBRKs00HAhQwb5VAC2jCud0gh%2BGpA0IC82cS40ZDRKzViAchoGcOJNRYH%2FqagMXlPF6Sxi0NuwXcNkaaSBjIxUt7XUroTMmFLcGALFdKoEZB6ss7cduIzSZEvcQKQ0Z%2BADiNiddmEdUXx%2Br41LZoiYruGWIKmG%2FsRFM%2F%2B4JjVLO%2FXz0vtth7xdh7Zjm%2FAF2w7OYv8vuqM9RNduw7d9Nmsx4jNF1XeUDZkFBvts1iKN44gHVOPeW8lk%2B2zm7bziIohSXID%2BTMpEt2XMxILpexke38ex%2FxyhzQXXnEb8B9vhcqQqRhe%2B0UgTLuZgp%2Fd6q%2Fm9XrX3b2Ot7FK9H43Gk9vR5fDiy3DycXROYpxyxx9cIGvU%2FmqtfRDYu5BotFZJHoBMMAEzycPGo1ZvR9fDq6tP50NSJtNzInVl8TFv1dM69XaRCfT7htryben4W3lTW3yIsf%2B9dmWHGHbLL7cpsrx1zw7h0HuMbXfMLn3qQHPq7CMQW0d80Oby8lAs%2FeWxVPSngzl6JpgPn9%2BNx8MxubAJVa%2B7a5fALf0v08kUsQXlgizdfSSzV1uD1F4szy6adwsXZvkp9kF%2BVnircwTCnOJQ4VXFmOUhcoqtOOuED2Sqa%2BtLoAp1YDq8ZctaavEpRuB4gJWkC6d4eJxhiR1A98S%2BFXOGB3IR84ip9ePemXded80gVr0N3AZuBrCKm28Eg3Xedp3iBjEZ6%2BqzwWmhdwP8SOi8gdaoGmYPLEi1rIVqXXz6V6rFDf5%2BAeea5M8%3D[Run this example on Compiler Explorer^] [#registering_classes_by_reflection] From 5ed0dd14303169baf1fc98d2ab02c1c83c5feae5 Mon Sep 17 00:00:00 2001 From: Jean-Louis Leroy Date: Sun, 18 Oct 2026 10:40:02 -0400 Subject: [PATCH 08/11] doc: ast.cpp prints the expression from a demo function main() builds the expression and hands it to demo(), which prints it and its value. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01958YRGfNfb6SfQS9v4hWTr --- doc/modules/ROOT/examples/ast.cpp | 8 ++++++-- doc/modules/ROOT/pages/basics.adoc | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/doc/modules/ROOT/examples/ast.cpp b/doc/modules/ROOT/examples/ast.cpp index 325ac8cec..6912cbd7c 100644 --- a/doc/modules/ROOT/examples/ast.cpp +++ b/doc/modules/ROOT/examples/ast.cpp @@ -72,12 +72,16 @@ BOOST_OPENMETHOD_OVERRIDE( BOOST_OPENMETHOD_CLASSES(Node, Variable, Plus, Times); // end::class_registration[] +void demo(const Node& e) { + postfix(e, std::cout); + std::cout << " = " << e.value() << "\n"; // 2 3 + 4 * = 20 +} + int main() { boost::openmethod::initialize(); Variable a{2}, b{3}, c{4}; Plus d{a, b}; Times e{d, c}; - postfix(e, std::cout); - std::cout << " = " << e.value() << "\n"; // 2 3 + 4 * = 20 + demo(e); } // end::content[] diff --git a/doc/modules/ROOT/pages/basics.adoc b/doc/modules/ROOT/pages/basics.adoc index e64caf97e..5d27494ad 100644 --- a/doc/modules/ROOT/pages/basics.adoc +++ b/doc/modules/ROOT/pages/basics.adoc @@ -114,7 +114,7 @@ Putting it all together: include::{examplesdir}/ast.cpp[tag=content] ---- -link:https://godbolt.org/clientstate/eNrFVn9r2zAQ%2FSqHB63SOE2Tlo3FiWFbAxtsTWlC%2F1m6othqKnAkI8umm%2FE%2B%2B06ynZ9t17GMKUS2n57u3Vmnk3MnYUnCpUicHnzNHR7iteOCE1ExT%2Bmc4aMTNJsOQolMVWCBRKs00HAhQwb5VAC2jCud0gh%2BGpA0IC82cS40ZDRKzViAchoGcOJNRYH%2FqagMXlPF6Sxi0NuwXcNkaaSBjIxUt7XUroTMmFLcGALFdKoEZB6ss7cduIzSZEvcQKQ0Z%2BADiNiddmEdUXx%2Br41LZoiYruGWIKmG%2FsRFM%2F%2B4JjVLO%2FXz0vtth7xdh7Zjm%2FAF2w7OYv8vuqM9RNduw7d9Nmsx4jNF1XeUDZkFBvts1iKN44gHVOPeW8lk%2B2zm7bziIohSXID%2BTMpEt2XMxILpexke38ex%2FxyhzQXXnEb8B9vhcqQqRhe%2B0UgTLuZgp%2Fd6q%2Fm9XrX3b2Ot7FK9H43Gk9vR5fDiy3DycXROYpxyxx9cIGvU%2FmqtfRDYu5BotFZJHoBMMAEzycPGo1ZvR9fDq6tP50NSJtNzInVl8TFv1dM69XaRCfT7htryben4W3lTW3yIsf%2B9dmWHGHbLL7cpsrx1zw7h0HuMbXfMLn3qQHPq7CMQW0d80Oby8lAs%2FeWxVPSngzl6JpgPn9%2BNx8MxubAJVa%2B7a5fALf0v08kUsQXlgizdfSSzV1uD1F4szy6adwsXZvkp9kF%2BVnircwTCnOJQ4VXFmOUhcoqtOOuED2Sqa%2BtLoAp1YDq8ZctaavEpRuB4gJWkC6d4eJxhiR1A98S%2BFXOGB3IR84ip9ePemXded80gVr0N3AZuBrCKm28Eg3Xedp3iBjEZ6%2BqzwWmhdwP8SOi8gdaoGmYPLEi1rIVqXXz6V6rFDf5%2BAeea5M8%3D[Run this example on Compiler Explorer^] +link:https://godbolt.org/clientstate/eNrFVn9r2zAQ%2FSqHB63TOE2Tlo3FiWFbAxtsTWlK%2F1m6othqKnAkI8umm%2FE%2B%2B06yld%2FtOpYxh8j209O9O0t3UuGkNE2Z4KnTg6%2BFwyK8dzxwYsJnGZlRfHXCZtNBKBWZDA2QKpmFCi5ERKGYcMArZ1JlJIafGnQbUJTrOOMKchJnui9EOQUDOPEnvMT%2FhNcGb4hkZBpT6K3ZtrC7MNJARu7Wj1ZqW0LkVEqmDYGkKpMcch9W2ZsOXMZZuiGuIbcyp%2BEDiOm98mAVkWz2oLRLusvVTcOrQLfu%2BhMX9fhjS2pWduz7wvtNh%2FxthzZju2Zzuhmcwf5fdEd7iK7dhm%2F7vIzFmE0lkd9RNqIGGOzzMhZJksQsJApzbymT7%2FPSX%2BcV42Gc4QT0p0Kkqi0SyudUPYjo%2BCFJgucIbcaZYiRmP%2BgWlyFVUjIPtEaWMj4DM7zXW47v9ercv0uUNFP1fjQaX9%2BNLocXX4bXH0fnboJD7tmjB%2B4Ktb%2Bc6wA4th6kCq3VkgcgUlyAuWBRY6fVu9HN8Orq0%2FnQrRbTcyK2sgS4buXTOjZdRAr9vqa2AlM6%2FlZe15YAEmx%2Fr13bcTW7FVRpiix%2F1bNDOPR3sU3GbNMnDjQnzj4CMXUkAKVvLw%2FF0F8eS01%2FOpijZ4L58PndeDwcuxdmQdl598wUeJX%2F1XLSnkJE52KtLNIt5%2B2yDEWmrCcLoHZooBt8pIuKZ%2FAJ6jg%2BYL534RRL%2FBkWwgF0T2rfdRmdE8bdheaO3Fomp2vVF7snKbqlB9PiFNuwOCv95U4GUUGwq%2FTr7YAWEXIsw4RNG9VH1Ft%2BKOYJi6lcPR04s87rru7EIrmGGy91BxZ9faTQWOdt1ylvEROJqk8ZTgs%2F0wDPFJ030BrV3fSRhpkSVsjq4tu%2FUi1v8fcLjHf0ZQ%3D%3D[Run this example on Compiler Explorer^] [#registering_classes_by_reflection] From 6849f36b34bbab5e3e2522eccce162a6ba6908d5 Mon Sep 17 00:00:00 2001 From: Jean-Louis Leroy Date: Sun, 18 Oct 2026 10:46:36 -0400 Subject: [PATCH 09/11] doc: Compiler Explorer links use clang 23.1 throughout The motivation and basics links compiled with gcc 16.2; make clang 23.1, which the performance comparison already used, the default of dev/ce_link.py, and regenerate them. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01958YRGfNfb6SfQS9v4hWTr --- dev/ce_link.py | 5 ++--- doc/modules/ROOT/pages/basics.adoc | 2 +- doc/modules/ROOT/pages/motivation.adoc | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/dev/ce_link.py b/dev/ce_link.py index d319f53a5..3a5c224b3 100755 --- a/dev/ce_link.py +++ b/dev/ce_link.py @@ -19,8 +19,7 @@ compiler pane, to compare the assembly: dev/ce_link.py doc/modules/ROOT/examples/dispatch_open_method.cpp \\ - --beside doc/modules/ROOT/examples/dispatch_virtual_function.cpp \\ - --compiler clang2310 + --beside doc/modules/ROOT/examples/dispatch_virtual_function.cpp An example that includes a Boost header gets the Boost release that Compiler Explorer offers in its Libraries dropdown, not the headers of this tree. @@ -35,7 +34,7 @@ import zlib from pathlib import Path -COMPILER = "g162" # x86-64 gcc 16.2; clang2310 is x86-64 clang 23.1.0 +COMPILER = "clang2310" # x86-64 clang 23.1.0 OPTIONS = "-std=c++17 -O2" BOOST = "192" # Boost 1.92.0, as Compiler Explorer names it FILTERS = { diff --git a/doc/modules/ROOT/pages/basics.adoc b/doc/modules/ROOT/pages/basics.adoc index 5d27494ad..8b7601877 100644 --- a/doc/modules/ROOT/pages/basics.adoc +++ b/doc/modules/ROOT/pages/basics.adoc @@ -114,7 +114,7 @@ Putting it all together: include::{examplesdir}/ast.cpp[tag=content] ---- -link:https://godbolt.org/clientstate/eNrFVn9r2zAQ%2FSqHB63TOE2Tlo3FiWFbAxtsTWlK%2F1m6othqKnAkI8umm%2FE%2B%2B06yld%2FtOpYxh8j209O9O0t3UuGkNE2Z4KnTg6%2BFwyK8dzxwYsJnGZlRfHXCZtNBKBWZDA2QKpmFCi5ERKGYcMArZ1JlJIafGnQbUJTrOOMKchJnui9EOQUDOPEnvMT%2FhNcGb4hkZBpT6K3ZtrC7MNJARu7Wj1ZqW0LkVEqmDYGkKpMcch9W2ZsOXMZZuiGuIbcyp%2BEDiOm98mAVkWz2oLRLusvVTcOrQLfu%2BhMX9fhjS2pWduz7wvtNh%2FxthzZju2Zzuhmcwf5fdEd7iK7dhm%2F7vIzFmE0lkd9RNqIGGOzzMhZJksQsJApzbymT7%2FPSX%2BcV42Gc4QT0p0Kkqi0SyudUPYjo%2BCFJgucIbcaZYiRmP%2BgWlyFVUjIPtEaWMj4DM7zXW47v9ercv0uUNFP1fjQaX9%2BNLocXX4bXH0fnboJD7tmjB%2B4Ktb%2Bc6wA4th6kCq3VkgcgUlyAuWBRY6fVu9HN8Orq0%2FnQrRbTcyK2sgS4buXTOjZdRAr9vqa2AlM6%2FlZe15YAEmx%2Fr13bcTW7FVRpiix%2F1bNDOPR3sU3GbNMnDjQnzj4CMXUkAKVvLw%2FF0F8eS01%2FOpijZ4L58PndeDwcuxdmQdl598wUeJX%2F1XLSnkJE52KtLNIt5%2B2yDEWmrCcLoHZooBt8pIuKZ%2FAJ6jg%2BYL534RRL%2FBkWwgF0T2rfdRmdE8bdheaO3Fomp2vVF7snKbqlB9PiFNuwOCv95U4GUUGwq%2FTr7YAWEXIsw4RNG9VH1Ft%2BKOYJi6lcPR04s87rru7EIrmGGy91BxZ9faTQWOdt1ylvEROJqk8ZTgs%2F0wDPFJ030BrV3fSRhpkSVsjq4tu%2FUi1v8fcLjHf0ZQ%3D%3D[Run this example on Compiler Explorer^] +link:https://godbolt.org/clientstate/eNrFVn9r2zAQ%2FSqHB63SOE2TFsbixLCtgRW2pDSl%2FyxdUWw1FTiWkWXTzXiffSfZys%2B261jGHCLbT0%2F37izdSYWTsjTlIk6dHnwtHB7iveOCE9F4ntE5w1cnaDYdhFKRycAAqZJZoGAkQgbFNAa8ci5VRiP4qUHSgKLcxHmsIKdRpvsClFMwgBNvGpf4n8a1wRsqOZ1FDHobti1MlkYayMhJ%2FWildiVEzqTk2hBIpjIZQ%2B7BOnvbgcsoS7fENUQqcxo%2BgIjdKxfWEcnnD0q7pLuIbhpuBZK6609c1OOPLalZ2bHvS%2B%2B3HfJ2HdqO7Zov2HZwBvt%2F0R3tIbp2G77t8zIWIz6TVH5H2ZAZYLDPy1ikSRLxgCrMvZVMvs9Lf503PA6iDCegPxMiVW2RsHjB1IMIjx%2BSxH%2BJ0OYxV5xG%2FAfb4XKkSkYXvtbIUh7PwQzv9Vbje7069%2B8SJc1UfRiPJ9d348vh6Mvw%2BtP4nCQ45J4%2FukDWqP3VXPsQY%2BtCqtBaLXkAIsUFmAseNp60eje%2BGV5dXZwPSbWYXhKxlcXHdSuf17HpIlLo9zW15ZvS8bfyurb4kGD7e%2B3aDtHsll%2BlKbK8dc8O4dB7im0yZpc%2BdaA5dfYRiKkjPih9e30ohv76WGr688EcvRDMx8%2FvJ5PhhIzMgrLz7popcCv%2Fq%2BWkPYWQLcRGWWQ7zttlGYhMWU%2BWQO3QQDf4yJYVz%2BBT1HE8wHzvwimW%2BDMshAPontS%2B6zK6oDwmS80ncmuVnMSqL3dPWnRLF2bFKbZBcVZ6q50MwoJiV%2BnV2wErQuRYhgmbNaqPqLf8QCwSHjG5fjpwAn026J52TjQDK%2BVGp3FVd2Dl1%2BcKjXXedZ3yFjGRqPqo4bTwWw3wYNF5C61x3c0eWZApYdWsOL79U%2BnyFn%2B%2FAJCJ9%2Fs%3D[Run this example on Compiler Explorer^] [#registering_classes_by_reflection] diff --git a/doc/modules/ROOT/pages/motivation.adoc b/doc/modules/ROOT/pages/motivation.adoc index 9db7146af..8bd1a2bf8 100644 --- a/doc/modules/ROOT/pages/motivation.adoc +++ b/doc/modules/ROOT/pages/motivation.adoc @@ -50,7 +50,7 @@ int main() { } ---- -link:https://godbolt.org/clientstate/eNrNVMtu2zAQ%2FJUFCyRy7DysBClg2v2EtoeilyoHmmJcAjRp8CEEINRv71KmHEnJJemhkQGanF3Ozo4oRuKEc9JoR1bwKxJZ4%2F9yAUQxvQtsJ3BJ%2BHxOEHImWN4Bn6TmKtQC1tI4bwXbf6l0pXEauIevBiOx0oBPI60PTMGfBBYziO0Yl9pDw1RIMY4qPGzgho5zGiNrOGChR%2FlUOF%2BvVrnoGRg33tbSgY6fzEq2VQJWI0k9XJxqzzCjKfK0V%2FhSmWmEtTIRgRU%2BWA0NhfYdWgdExsF6PeDpqk4b%2Ba6CmzSRoOLIluAzUOLRL2CIWLn77VNrKVSkYbY4gkUOvaXVtP%2BqT5ofefr1swtv6%2F64KT0de78RU2k25hzOaa71SrQiMK9IPi1ZwtQT%2BtKTqb0%2F5F5M%2Fe2w%2F2fwxYcx%2BOJfDE5975nU6cMff3zAYtkuYBtvceTxrqXP5xrqyDDU0vxmRKwxp88QV6P%2BuQl%2BlkMnIGvfpAGn4uRrh1cojVC4voYSbvEs36HdGyhvUHWl00XHzf4glbDDO5HslvdlCiq57fAHnJuDz1cnucTiG7wol5%2Fh8ltJ2hQWT4IHb3qenhZX7yRtH%2FD3F%2F4S1Xc%3D[Run this example on Compiler Explorer^] +link:https://godbolt.org/clientstate/eNrNVE1v2zAM%2FSuEBrROk7aJU2BAlOwnbDsMu8w9KLKaCVCkQB9GAcH77aMcObXdXboeNhmQpUeKfHyWGYkTzkmjHdnAj0hkje%2FVAohi%2BhDYQeCW8PmcIORMsLwDPkjNVagFbKVx3gp2%2FFTpSuMycA%2BfDVpipQFHI60PTMGvBBYziO0Yl9pDw1RINo4sPOxgScc%2BjZE1nDDRk3wunK83m5z0CowbH2vpgMd3ZiXbKwGbEaUeLi65Z%2BjRFHnZM3zNzDTCWpkCgRU%2BWA0NhfYvuA4CGQfb7SBOl3VayFcV3KSIBBXnaAm%2BAiWe%2FAKGiJWHnz6VlkxFmmaLM1hk01tKTefveqf5OU6%2Ff1HhbdWfD6XRRe8PoivNwlzDNc25%2FmCtCMwrkm9LpjDVhL7WZCrvN3kUU3077N8JfPPfCHzzHoFT3Ucmdfrxxz8fsFi2C9jHNc48PrT05V5DHRmaWpq%2FjIg1%2BvQe4m5UPzfBz7LpAmTuuzThUlx07fAKqREK9%2FdQwhrv8gPKvYNyiawrnRodN8eTVMIOeyLhqSOW69UyeSi574yPuDYnn%2FsnuUUGO%2ByWq49w%2B6UkbTKLZ8GDN32wPjbu3hO5fcTnN6uK2Q0%3D[Run this example on Compiler Explorer^] If the classes are part of a small, self-contained program, this may be a reasonable solution. From 1cbd7498b9e4ba24a636fe9f756fbf1ebf797582 Mon Sep 17 00:00:00 2001 From: Jean-Louis Leroy Date: Sun, 18 Oct 2026 10:48:46 -0400 Subject: [PATCH 10/11] doc: motivation examples print from a demo function As ast.cpp does: main() builds the expression and hands it to demo(). Both programs on the page change together, so that the postfix listing still reads as the first one plus postfix. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01958YRGfNfb6SfQS9v4hWTr --- doc/modules/ROOT/examples/ast_virtual_function.cpp | 6 +++++- doc/modules/ROOT/examples/ast_virtual_function_2.cpp | 8 ++++++-- doc/modules/ROOT/pages/motivation.adoc | 10 +++++++--- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/doc/modules/ROOT/examples/ast_virtual_function.cpp b/doc/modules/ROOT/examples/ast_virtual_function.cpp index d60f0b1cd..64feaa74b 100644 --- a/doc/modules/ROOT/examples/ast_virtual_function.cpp +++ b/doc/modules/ROOT/examples/ast_virtual_function.cpp @@ -31,9 +31,13 @@ struct Times : Node { const Node& left; const Node& right; }; +void demo(const Node& e) { + std::cout << e.value() << "\n"; // 20 +} + int main() { Variable a{2}, b{3}, c{4}; Plus d{a, b}; Times e{d, c}; - std::cout << e.value() << "\n"; // 20 + demo(e); } // end::content[] diff --git a/doc/modules/ROOT/examples/ast_virtual_function_2.cpp b/doc/modules/ROOT/examples/ast_virtual_function_2.cpp index 28670cd5e..c0872c461 100644 --- a/doc/modules/ROOT/examples/ast_virtual_function_2.cpp +++ b/doc/modules/ROOT/examples/ast_virtual_function_2.cpp @@ -39,11 +39,15 @@ struct Times : Node { const Node& left; const Node& right; }; +void demo(const Node& e) { + e.postfix(std::cout); + std::cout << " = " << e.value() << "\n"; // 2 3 + 4 * = 20 +} + int main() { Variable a{2}, b{3}, c{4}; Plus d{a, b}; Times e{d, c}; - e.postfix(std::cout); - std::cout << " = " << e.value() << "\n"; // 2 3 + 4 * = 20 + demo(e); } // end::all[] diff --git a/doc/modules/ROOT/pages/motivation.adoc b/doc/modules/ROOT/pages/motivation.adoc index 8bd1a2bf8..df6a7b0ef 100644 --- a/doc/modules/ROOT/pages/motivation.adoc +++ b/doc/modules/ROOT/pages/motivation.adoc @@ -42,15 +42,19 @@ struct Times : Node { } }; +void demo(const Node& e) { + e.postfix(std::cout); // 2 3 + 4 * + std::cout << " = " << e.value() << "\n"; // = 20 +} + int main() { Variable a{2}, b{3}, c{4}; Plus d{a, b}; Times e{d, c}; - e.postfix(std::cout); // 2 3 + 4 * - std::cout << " = " << e.value() << "\n"; // = 20 + demo(e); } ---- -link:https://godbolt.org/clientstate/eNrNVE1v2zAM%2FSuEBrROk7aJU2BAlOwnbDsMu8w9KLKaCVCkQB9GAcH77aMcObXdXboeNhmQpUeKfHyWGYkTzkmjHdnAj0hkje%2FVAohi%2BhDYQeCW8PmcIORMsLwDPkjNVagFbKVx3gp2%2FFTpSuMycA%2BfDVpipQFHI60PTMGvBBYziO0Yl9pDw1RINo4sPOxgScc%2BjZE1nDDRk3wunK83m5z0CowbH2vpgMd3ZiXbKwGbEaUeLi65Z%2BjRFHnZM3zNzDTCWpkCgRU%2BWA0NhfYvuA4CGQfb7SBOl3VayFcV3KSIBBXnaAm%2BAiWe%2FAKGiJWHnz6VlkxFmmaLM1hk01tKTefveqf5OU6%2Ff1HhbdWfD6XRRe8PoivNwlzDNc25%2FmCtCMwrkm9LpjDVhL7WZCrvN3kUU3077N8JfPPfCHzzHoFT3Ucmdfrxxz8fsFi2C9jHNc48PrT05V5DHRmaWpq%2FjIg1%2BvQe4m5UPzfBz7LpAmTuuzThUlx07fAKqREK9%2FdQwhrv8gPKvYNyiawrnRodN8eTVMIOeyLhqSOW69UyeSi574yPuDYnn%2FsnuUUGO%2ByWq49w%2B6UkbTKLZ8GDN32wPjbu3hO5fcTnN6uK2Q0%3D[Run this example on Compiler Explorer^] +link:https://godbolt.org/clientstate/eNrNVMtu2zAQ%2FJUFCyRS7CS2HKCAZecT0hyKXqocaIpxCUiiwYcQQFC%2FPbsS5UhKL2kOrQzQ5OxydnZAsmFWWqt0ZdkWfjZM5fi%2FXgIreHX0%2FChxycRiwRCy2hvRAV9UJQqfS9gpbZ2RvLzPqqzCqRcOHjRGmqwC%2FGplnOcF%2FCYwiqFpp7iqHNS88BQTqMLBHlbpNKfWKocTFnpWL5F1%2BXYbil6AttNtbTrS8YMbxQ%2BFhO1E0gBH59oxZtRRmA4K3yvTtTRGEREY6bypoE6h%2FQutIyJtYbcb8XRV5408Ft7OmiAo6tkIvoBCPrsljBGjjr8ctUahiIZ42YNRCH2kVdp%2FMyQtep5h%2FebCx7rvN9HXsQ8bMTUNxlzCZRpq%2FSGaMVhkLJyWIGHuSfrek7m931Up5%2F522L8z%2BOq%2FMfjqMwZ3cnNZ6omTdMl6Lnkz6UVo7%2BJQ7QwEHXsacCrPHnV4hmVYCre3kMAGz%2BUdWreHZIUKSAAZX3JVRfH89gNvknYJh2aDo2ju2vTtYkHecAy1aTgasskxZ8jo%2BpGkE0vQuyh0eVKFNOMnlAl6QJPNekUZhTp0wSec65MLzy27xib3%2BLiuv8L1t4S1FJYvUninB7KBG1efYW6f8PcK2LHoow%3D%3D[Run this example on Compiler Explorer^] If the classes are part of a small, self-contained program, this may be a reasonable solution. From c5ddf51dc91fe7dd6c80c3c1c45ed7acc671f897 Mon Sep 17 00:00:00 2001 From: Jean-Louis Leroy Date: Sun, 18 Oct 2026 11:06:20 -0400 Subject: [PATCH 11/11] ci: run on pushes to doc/** branches Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01958YRGfNfb6SfQS9v4hWTr --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c0ec928a4..ce94fb8ea 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -29,6 +29,7 @@ on: - master - develop - bugfix/** + - doc/** - feature/** - fix/** - github/**