fix: allow final classes as SM deps and SM classes (#483)#680
Open
PavelGuzenfeld wants to merge 3 commits into
Open
fix: allow final classes as SM deps and SM classes (#483)#680PavelGuzenfeld wants to merge 3 commits into
PavelGuzenfeld wants to merge 3 commits into
Conversation
Two compilation errors triggered when a type marked final is used
either as a dependency or as the SM class itself.
Root cause 1 — is_empty<T>:
is_empty_base<T, none_type> inherits from T. The compiler rejects
this when T is final ('cannot derive from final base'). Fix: add a
partial specialisation guarded by __is_final(T) that derives from
false_type instead, so is_empty_base<T> is never instantiated for
final types.
Root cause 2 — sm_impl<Tsm> : Tsm::sm:
sm_impl inherits from the user's SM class unless
should_not_subclass_statemachine_class<Tsm> is true. That predicate
previously only checked is_empty (the EBO optimisation path) and the
explicit dont_instantiate_statemachine_class policy. Fix: extend the
predicate to also return true when __is_final(Tsm::sm) is true,
routing final SM classes through the existing composition path
(try_get_without_instantiating).
__is_final is a compiler builtin available on GCC, Clang and MSVC, used
here consistently with __is_base_of already present in the same header.
Tests added to test/ft/dependencies.cpp:
final_dependency_type_compiles — final dep type used in action
final_sm_class_compiles — final SM class itself
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Closes #483.
Types declared
finalcannot be used either as SM dependencies or as the SM class itself.The compiler rejects the code because SML internally tries to inherit from the type in two places.
Root Causes & Fixes
1.
is_empty<T>—is_empty_base<T>inherits fromTFix: add a partial specialisation guarded by
__is_final(T)that inherits fromfalse_typeinstead, sois_empty_base<T>is never instantiated for final types.2.
sm_impl<Tsm> : Tsm::sm—sm_implinherits from the SM classshould_not_subclass_statemachine_classpreviously only returnedtruefor empty SM classes (EBO) or when thedont_instantiate_statemachine_classpolicy was set.Fix: extend the predicate to also return
truewhen__is_final(Tsm::sm)is true. This routes final SM classes through the existing composition path (try_get_without_instantiating) which callsoperator()on the SM object without requiring inheritance.Notes
__is_finalis a compiler builtin available on GCC, Clang, and MSVC — used here consistently with__is_base_ofalready present in the same header.Tests
Two regression tests added to
test/ft/dependencies.cpp:final_dependency_type_compiles— final dep type used in an action lambdafinal_sm_class_compiles— SM class itself declared final