Skip to content

document operator, limitation for two raw MFP actions and show wrap() fix (issue #389)#678

Open
PavelGuzenfeld wants to merge 1 commit into
boost-ext:masterfrom
PavelGuzenfeld:fix/issue-389-mfp-comma-operator-wrap
Open

document operator, limitation for two raw MFP actions and show wrap() fix (issue #389)#678
PavelGuzenfeld wants to merge 1 commit into
boost-ext:masterfrom
PavelGuzenfeld:fix/issue-389-mfp-comma-operator-wrap

Conversation

@PavelGuzenfeld
Copy link
Copy Markdown
Contributor

Fixes #389.

Root cause

/ (&C::action_a, &C::action_b) uses the C++ built-in comma operator instead of the library's action-sequencing operator,. Raw member-function pointers are pointer types, not class types. The C++ standard only allows user-defined operator, to be selected when at least one operand is a class or enum type, so the built-in comma always wins for two raw MFPs — silently discarding the first action.

This is a C++ language constraint that cannot be removed at the library level.

Workaround: sml::wrap() the first MFP

sml::wrap() returns a zero_wrapper<MFP>, which is a class type. That satisfies the requirement and the user-defined operator, is selected:

// broken — only action_b runs
/ (&C::action_a, &C::action_b)

// correct — both action_a and action_b run
/ (sml::wrap(&C::action_a), &C::action_b)

Subsequent actions in the list (additional MFPs, lambdas, functors) chain correctly from there without extra wrap() calls, because each operator, already produces a class-typed seq_ result.

Changes

  • include/boost/sml.hpp: add a comment above the global operator, overload explaining the language constraint and the wrap() workaround.
  • example/actions_guards.cpp: replace the single-MFP action on the s5 transition with (wrap(&self::action4), &self::action5) to demonstrate two-MFP sequencing.
  • test/ft/transition_table.cpp: add member_functions_two_mfp_actions_with_wrap — verifies that both actions run when the first MFP is wrapped.

…oost-ext#389)

Two raw member-function-pointer actions combined with comma,
  / (&C::a, &C::b)
silently run only the last action.  Raw MFPs are pointer types, not
class types, so the C++ standard requires the built-in comma operator
to be selected regardless of any user-defined operator, overloads.
This is a language limitation that cannot be fixed in the library.

The workaround is to wrap the first MFP with sml::wrap():
  / (sml::wrap(&C::a), &C::b)
wrap() returns a zero_wrapper class type, enabling the user-defined
operator, overload that creates a seq_ action sequence.  Subsequent
actions (raw MFPs, lambdas, or functors) chain correctly from there.

Changes:
- Add an explanatory comment above operator, in sml.hpp describing
  the language constraint and the wrap() workaround.
- Update example/actions_guards.cpp: replace the single-MFP action
  on the s5 transition with (wrap(&self::action4), &self::action5)
  to demonstrate two-MFP sequencing.
- Add regression test member_functions_two_mfp_actions_with_wrap in
  test/ft/transition_table.cpp that verifies both actions execute.
@PavelGuzenfeld PavelGuzenfeld force-pushed the fix/issue-389-mfp-comma-operator-wrap branch from bedd4eb to d671f8a Compare May 24, 2026 20:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

First action not executed when using multiple member function actions

1 participant