Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ configure_package_config_file(

write_basic_package_version_file(
${CMAKE_CURRENT_BINARY_DIR}/smlConfigVersion.cmake
VERSION 1.1.13
VERSION 1.2.0
COMPATIBILITY SameMajorVersion
)

Expand Down
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,7 @@ send: 42
* [sm [state machine]](https://boost-ext.github.io/sml/user_guide.html#sm-state-machine)
* [policies [state machine]](https://boost-ext.github.io/sml/user_guide.html#policies-state-machine)
* [testing::sm [testing]](https://boost-ext.github.io/sml/user_guide.html#testingsm-testing)
* [make_action [utility]](https://boost-ext.github.io/sml/user_guide.html#make_action-utility)
* [make_dispatch_table [utility]](https://boost-ext.github.io/sml/user_guide.html#make_dispatch_table-utility)
* [Examples](https://boost-ext.github.io/sml/examples.html)
* [Hello World](https://boost-ext.github.io/sml/examples.html#hello-world)
Expand All @@ -312,7 +313,11 @@ send: 42
* [SDL2 Integration](https://boost-ext.github.io/sml/examples.html#sdl2-integration)
* [Plant UML Integration](https://boost-ext.github.io/sml/examples.html#plant-uml-integration)
* [FAQ](https://boost-ext.github.io/sml/faq.html)
* [Limitations](https://boost-ext.github.io/sml/faq.html#limitations)
* [`on_entry<_>` across translation units](https://boost-ext.github.io/sml/faq.html#on_entry_-across-translation-units)
* [`operator,` with two raw member-function-pointer actions](https://boost-ext.github.io/sml/faq.html#operator-with-two-raw-member-function-pointer-actions)
* [CHANGELOG](https://boost-ext.github.io/sml/CHANGELOG.html)
* [[1.2.0] - 2026-06-01](https://boost-ext.github.io/sml/CHANGELOG.html#120-2026-06-01)
* [[1.1.13] - 2025-12-01](https://boost-ext.github.io/sml/CHANGELOG.html#1113-2025-12-01)
* [[1.1.12] - 2025-04-02](https://boost-ext.github.io/sml/CHANGELOG.html#1112-2025-04-02)
* [[1.1.11] - 2024-03-09](https://boost-ext.github.io/sml/CHANGELOG.html#1111-2024-03-09)
Expand Down
24 changes: 24 additions & 0 deletions doc/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,27 @@
## [1.2.0] - 2026-06-01
- **Additions**
- `sm::flush_queue()` — drain pending queued events from async handlers (#456)
- `sml::clear_defer` action — discard deferred events from a transition (#643)
- `sml::deps<Ts...>` policy — explicit pool dependencies for generic-lambda actions/guards (#437)
- `sml::make_action<Deps...>(f)` — wrap a template/generic/constrained callable so its dependency and event types are deduced from the explicit `<Deps...>` list (#629)

- **Behavior changes**
- Empty-SM min-size trick is now OFF by default on GCC/Clang (it was UB at `-O2`);
opt back in with `BOOST_SML_CFG_ENABLE_MIN_SIZE`. `sizeof(sm)` for an empty SM may change (#249)
- `any`/`_` wildcard no longer fires when a composable sub-SM has terminated (#622)
- Events raised via `process(E{})` are now storable in the process queue (#580)
- Guard taking `const State&` now sees live pool state instead of a stale copy (#530)
- Sub-SM defer queue is cleared when its composite state is re-entered (#253)

- **Bug Fixes**
- Template-depth, `-Wshadow`, `-Wextra-semi`, UBSan, final-class, null-deref,
double-pop, reserved-identifier and related fixes — see full list:
- https://github.com/boost-ext/sml/compare/v1.1.13...v1.2.0

- **Documented limitations**
- `on_entry<_>` multi-TU linker limitation and dispatch priority (#565)
- `operator,` with two raw member-function-pointer actions; `wrap()` workaround (#389)

## [1.1.13] - 2025-12-01
- Changes
- https://github.com/boost-ext/sml/compare/v1.1.12...v1.1.13
Expand Down
22 changes: 22 additions & 0 deletions doc/examples.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,66 +25,88 @@

###Hello World
![CPP](https://raw.githubusercontent.com/boost-ext/sml/master/example/hello_world.cpp)
[▶ Run on Compiler Explorer](https://godbolt.org/z/dq85hW4ab)

###Events
![CPP](https://raw.githubusercontent.com/boost-ext/sml/master/example/events.cpp)
[▶ Run on Compiler Explorer](https://godbolt.org/z/s816cG5j8)

###States
![CPP](https://raw.githubusercontent.com/boost-ext/sml/master/example/states.cpp)
[▶ Run on Compiler Explorer](https://godbolt.org/z/c9asGjYTr)

###Actions Guards
![CPP](https://raw.githubusercontent.com/boost-ext/sml/master/example/actions_guards.cpp)
[▶ Run on Compiler Explorer](https://godbolt.org/z/nehrdofPx)

###Transitions
![CPP](https://raw.githubusercontent.com/boost-ext/sml/master/example/transitions.cpp)
[▶ Run on Compiler Explorer](https://godbolt.org/z/qr8qs78Ts)

###Defer/Process
![CPP](https://raw.githubusercontent.com/boost-ext/sml/master/example/defer_and_process.cpp)
[▶ Run on Compiler Explorer](https://godbolt.org/z/T7YaW61en)

###Orthogonal Regions
![CPP](https://raw.githubusercontent.com/boost-ext/sml/master/example/orthogonal_regions.cpp)
[▶ Run on Compiler Explorer](https://godbolt.org/z/vqGbsrqM3)

###Composite
![CPP](https://raw.githubusercontent.com/boost-ext/sml/master/example/composite.cpp)
[▶ Run on Compiler Explorer](https://godbolt.org/z/5sYb9eGbe)

###History
![CPP](https://raw.githubusercontent.com/boost-ext/sml/master/example/history.cpp)
[▶ Run on Compiler Explorer](https://godbolt.org/z/Pvz6Y7vd4)

###Error handling
![CPP](https://raw.githubusercontent.com/boost-ext/sml/master/example/error_handling.cpp)
[▶ Run on Compiler Explorer](https://godbolt.org/z/cGd7TnM1G)

###Logging
![CPP](https://raw.githubusercontent.com/boost-ext/sml/master/example/logging.cpp)
[▶ Run on Compiler Explorer](https://godbolt.org/z/Tec7jz36r)

###Nested
![CPP](https://raw.githubusercontent.com/boost-ext/sml/master/example/nested.cpp)
[▶ Run on Compiler Explorer](https://godbolt.org/z/xd9PoEPdn)

###Testing
![CPP](https://raw.githubusercontent.com/boost-ext/sml/master/example/testing.cpp)
[▶ Run on Compiler Explorer](https://godbolt.org/z/oc73h5sY8)

###Runtime Dispatcher
![CPP](https://raw.githubusercontent.com/boost-ext/sml/master/example/dispatch_table.cpp)
[▶ Run on Compiler Explorer](https://godbolt.org/z/j5bMnobY9)

###eUML Emulation
![CPP](https://raw.githubusercontent.com/boost-ext/sml/master/example/euml_emulation.cpp)
[▶ Run on Compiler Explorer](https://godbolt.org/z/n93Y5Mner)

###Dependencies
![CPP](https://raw.githubusercontent.com/boost-ext/sml/master/example/dependencies.cpp)
[▶ Run on Compiler Explorer](https://godbolt.org/z/afxWz4jq3)

###Data
![CPP](https://raw.githubusercontent.com/boost-ext/sml/master/example/data.cpp)
[▶ Run on Compiler Explorer](https://godbolt.org/z/P4vn1dK9e)

###In-Place
![CPP](https://raw.githubusercontent.com/boost-ext/sml/master/example/in_place.cpp)
[▶ Run on Compiler Explorer](https://godbolt.org/z/r43fKbz6z)

###Dependency Injection
![CPP](https://raw.githubusercontent.com/boost-ext/sml/master/example/dependency_injection.cpp)
[▶ Run on Compiler Explorer](https://godbolt.org/z/1Pv6EaG7n)

###Arduino Integration
![CPP](https://raw.githubusercontent.com/boost-ext/sml/master/example/arduino.cpp)
[▶ Run on Compiler Explorer](https://godbolt.org/z/Kfba9GovG)

###SDL2 Integration
![CPP](https://raw.githubusercontent.com/boost-ext/sml/master/example/sdl2.cpp)
[▶ Run on Compiler Explorer](https://godbolt.org/z/8heY58eE6)

###Plant UML Integration
![CPP](https://raw.githubusercontent.com/boost-ext/sml/master/example/plant_uml.cpp)
[▶ Run on Compiler Explorer](https://godbolt.org/z/8eT6aWsc9)
31 changes: 31 additions & 0 deletions doc/faq.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# FAQ

## Limitations

### `on_entry<_>` across translation units

When `on_entry<_>` (the wildcard entry handler) is defined in one translation unit
while the `initial`-event specialization is left undefined, the linker reports an
undefined reference. Make sure the entry handler is fully defined where it is used.

Dispatch priority: a specific `on_entry<e1>` handler takes priority over the
`on_entry<_>` wildcard. The wildcard fires only when no specific handler matches the
event used to enter the state.

```cpp
// on_entry<e1> fires when entering via e1 (specific handler wins)
// on_entry<_> fires when entering via any other event (no specific handler)
```

### `operator,` with two raw member-function-pointer actions

Two raw member-function-pointer actions combined with the comma operator
(`&A::f, &A::g`) select the built-in comma operator, because both operands are
class types — so SML's action-sequencing is bypassed. Wrap the actions with
`wrap(...)` to restore sequencing:

```cpp
*"s1"_s + event<e> / (wrap(&A::f), wrap(&A::g)) = X
```

See `example/actions_guards.cpp` for a worked example.
4 changes: 4 additions & 0 deletions doc/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,13 @@ to avoid it `[Boost].SML` may suit you!
###Real Life examples?

![CPP(BTN)](Run_SDL2_Integration_Example|https://raw.githubusercontent.com/boost-ext/sml/master/example/sdl2.cpp)
[▶ Run on Compiler Explorer](https://godbolt.org/z/8heY58eE6)
![CPP(BTN)](Run_Plant_UML_Example|https://raw.githubusercontent.com/boost-ext/sml/master/example/plant_uml.cpp)
[▶ Run on Compiler Explorer](https://godbolt.org/z/8eT6aWsc9)
![CPP(BTN)](Run_Logging_Example|https://raw.githubusercontent.com/boost-ext/sml/master/example/logging.cpp)
[▶ Run on Compiler Explorer](https://godbolt.org/z/Tec7jz36r)
![CPP(BTN)](Run_Testing_Example|https://raw.githubusercontent.com/boost-ext/sml/master/example/testing.cpp)
[▶ Run on Compiler Explorer](https://godbolt.org/z/oc73h5sY8)

&nbsp;

Expand Down
16 changes: 15 additions & 1 deletion doc/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,17 @@ git clone https://github.com/boost-ext/sml && cd sml && make test
###Configuration
| Macro | Description |
| --------------------------------------------------------------|--------------------------------------------------------------|
| `BOOST_SML_VERSION` | Current version of [Boost].SML (ex. 1'0'0) |
| `BOOST_SML_VERSION` | Current version of [Boost].SML (ex. 1'1'13) |
| `BOOST_SML_CFG_ENABLE_MIN_SIZE` | Opt in to the empty-SM size trick (zero-size array); disabled by default, see note below |
| `BOOST_SML_CFG_DISABLE_MIN_SIZE` | Legacy name kept for backward compatibility; the min-size trick is now disabled by default |
| `BOOST_SML_DISABLE_EXCEPTIONS` | Build with exceptions disabled (e.g. with `-fno-exceptions`) |
| `BOOST_SML_CREATE_DEFAULT_CONSTRUCTIBLE_DEPS` | Allow default-constructing dependencies owned by the State Machine |

> **Note (min-size):** Since the changes after `v1.1.13`, the empty-State-Machine
> size optimization is **off by default** on GCC/Clang because the zero-length-array
> trick triggered undefined behavior at `-O2` (UBSan violations). As a result,
> `sizeof(sm<...>)` for an empty State Machine may differ from earlier releases.
> Define `BOOST_SML_CFG_ENABLE_MIN_SIZE` to opt back in.


###Exception Safety
Expand Down Expand Up @@ -83,15 +93,19 @@ sm.process_event(event{}); // thread safe call

***Not configurable***
![CPP](https://raw.githubusercontent.com/boost-ext/sml/master/test/ft/errors/not_configurable.cpp)
[▶ See the compile error on Compiler Explorer](https://godbolt.org/z/zehzezMoe)

***Not callable***
![CPP](https://raw.githubusercontent.com/boost-ext/sml/master/test/ft/errors/not_callable.cpp)
[▶ See the compile error on Compiler Explorer](https://godbolt.org/z/fb8K6q4WK)

***Not transitional***
![CPP](https://raw.githubusercontent.com/boost-ext/sml/master/test/ft/errors/not_transitional.cpp)
[▶ See the compile error on Compiler Explorer](https://godbolt.org/z/3aWdcTanT)

***Not dispatchable***
![CPP](https://raw.githubusercontent.com/boost-ext/sml/master/test/ft/errors/not_dispatchable.cpp)
[▶ See the compile error on Compiler Explorer](https://godbolt.org/z/984KoaP6x)

[Boost.MSM-eUML]: http://www.boost.org/doc/libs/1_60_0/libs/msm/doc/HTML/ch03s04.html
[Boost.MSM3-eUML2]: https://htmlpreview.github.io/?https://raw.githubusercontent.com/boostorg/msm/msm3/doc/HTML/ch03s05.html
Expand Down
85 changes: 85 additions & 0 deletions doc/scripts/gen_godbolt_links.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
#!/usr/bin/env bash
#
# Regenerate the "Run on Compiler Explorer" links embedded in the docs.
#
# Boost.SML is a single-header library that is NOT registered as a Compiler
# Explorer library. Each godbolt.org/z/ link keeps the example source intact and
# pulls the header via Compiler Explorer's client-side "#include from URL" feature:
# #include <https://raw.githubusercontent.com/boost-ext/sml/master/include/boost/sml.hpp>
# CE fetches and pastes that header in the browser when the link is opened (it is
# NOT resolved by the compile API). dispatch_table.hpp itself does a relative
# `#include "boost/sml.hpp"`, which CE's fetcher cannot resolve, so for the two
# examples that use it (dispatch_table, sdl2) the small utility header is inlined
# with its own sml.hpp include rewritten to the URL form.
#
# The error/* examples intentionally fail to compile and get compile-only links
# that show the diagnostic.
#
# Requirements: bash, curl, jq. Run from the repository root.
# Usage:
# doc/scripts/gen_godbolt_links.sh # print "name url" for every example
# doc/scripts/gen_godbolt_links.sh --insert # also rewrite the CE links in doc/*.md
#
set -euo pipefail
cd "$(git rev-parse --show-toplevel)"

GCC=g142 # Compiler Explorer GCC 14.2
STD_DEFAULT=c++14 # SML's minimum standard
DT=include/boost/sml/utility/dispatch_table.hpp
URL='https://raw.githubusercontent.com/boost-ext/sml/master/include/boost/sml.hpp'

assemble() { # <src.cpp> -> thin url-include source on stdout
# Rewrite `#include <boost/sml.hpp>` to the URL form; for the dispatch_table.hpp
# include, inline that small header with its own sml.hpp include rewritten too.
awk -v url="$URL" -v dt="$DT" '
/#include[ \t]*[<"]boost\/sml\.hpp[>"]/ { print "#include <" url ">"; next }
/#include[ \t]*[<"]boost\/sml\/utility\/dispatch_table\.hpp[>"]/ {
while ((getline l < dt) > 0)
if (l ~ /#include[ \t]*[<"]boost\/sml\.hpp[>"]/) print "#include <" url ">"; else print l
close(dt); next }
{ print }
' "$1"
}

shorten() { # <assembled-file> <std> <execute:true|false> -> godbolt short url
local src="$1" std="$2" exec="$3"
jq -n --rawfile s "$src" --arg std "$std" --argjson ex "$exec" \
'{sessions:[{id:1,language:"c++",source:$s,
compilers:[{id:"'"$GCC"'",options:("-O2 -std="+$std),libs:[],
filters:{execute:$ex,labels:true,directives:true,commentOnly:true,trim:true,demangle:true}}],
executors:(if $ex then [{compiler:{id:"'"$GCC"'",options:("-O2 -std="+$std),libs:[],overrides:[]},
arguments:"",stdin:"",compilerOutputVisible:true,stdoutVisible:true,stderrVisible:true}] else [] end)}]}' \
| curl -s -X POST 'https://godbolt.org/api/shortener' -H 'Content-Type: application/json' -d @- | jq -r '.url'
}

MAP=$(mktemp)
process() { # <src.cpp> <execute:true|false>
local ex="$1" exec="$2" name std tmp url
name=$(basename "$ex" .cpp)
std=$STD_DEFAULT; [ "$name" = arduino ] && std=c++20 # template lambdas
tmp=$(mktemp); assemble "$ex" > "$tmp"
url=$(shorten "$tmp" "$std" "$exec"); rm -f "$tmp"
echo "$name $url" | tee -a "$MAP"
}

for f in example/*.cpp; do process "$f" true; done
for f in test/ft/errors/not_*.cpp; do process "$f" false; done

if [ "${1:-}" = "--insert" ]; then
# strip previously-generated CE links, then re-insert after each embed.
# Only delete a CE link that immediately FOLLOWS an ![CPP] embed, so standalone
# links (e.g. the make_action example in the user guide) are preserved.
DOCS=(doc/examples.md doc/tutorial.md doc/user_guide.md doc/index.md doc/overview.md)
for d in "${DOCS[@]}"; do
awk '{ if (prev ~ /!\[CPP/ && $0 ~ /Compiler Explorer\]\(https:\/\/godbolt\.org/) { prev=$0; next } print; prev=$0 }' "$d" > "$d.tmp" && mv "$d.tmp" "$d"
done
while read -r name url; do
case "$name" in
not_*) label="▶ See the compile error on Compiler Explorer";;
*) label="▶ Run on Compiler Explorer";;
esac
for d in "${DOCS[@]}"; do sed -i "\#/${name}\.cpp)#a [$label]($url)" "$d"; done
done < "$MAP"
echo "docs updated."
fi
rm -f "$MAP"
2 changes: 1 addition & 1 deletion doc/themes/boost-modern/footer.html
Original file line number Diff line number Diff line change
Expand Up @@ -39,5 +39,5 @@
{% endif %}
</div>

Built with <a href="http://www.mkdocs.org">MkDocs</a> using a <a href="https://github.com/snide/sphinx_rtd_theme">theme</a> provided by <a href="https://readthedocs.org">Read the Docs</a> | Powered by <a href="http://melpon.org/wandbox">Wandbox</a>
Built with <a href="http://www.mkdocs.org">MkDocs</a> using a <a href="https://github.com/snide/sphinx_rtd_theme">theme</a> provided by <a href="https://readthedocs.org">Read the Docs</a> | Powered by <a href="https://wandbox.org">Wandbox</a>
</footer>
7 changes: 5 additions & 2 deletions doc/themes/boost-modern/js/cpp.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ function compile_and_run(id) {
document.getElementById("compile_and_run_" + id).firstChild.data = "Compiling...";
cpp_output[id].setValue("Compiling...");
var http = new XMLHttpRequest();
http.open("POST", "http://melpon.org/wandbox/api/compile.json", true);
http.open("POST", "https://wandbox.org/api/compile.json", true);
http.onreadystatechange = function(){
if (http.readyState == 4 && http.status == 200) {
var output_json = JSON.parse(http.response);
Expand All @@ -74,8 +74,11 @@ function compile_and_run(id) {
, "codes" : [{
"file" : "boost/sml.hpp"
, "code" : get_cpp_file("https://raw.githubusercontent.com/boost-ext/sml/master/include/boost/sml.hpp")
}, {
"file" : "boost/sml/utility/dispatch_table.hpp"
, "code" : get_cpp_file("https://raw.githubusercontent.com/boost-ext/sml/master/include/boost/sml/utility/dispatch_table.hpp")
}]
, "options": "warning,cpp-pedantic-errors,optimize,boost-1.60,c++1y"
, "options": "warning,cpp-pedantic-errors,optimize,c++1y"
, "compiler" : "clang-head"
, "compiler-option-raw": "-I." + "\n" + "-fno-color-diagnostics"
}));
Expand Down
Loading
Loading