Skip to content

Compilation error with virtual substate machine class #641

@da-woods

Description

@da-woods

In the code below:

struct S1{};

struct E1 {};

struct BSSM {
    virtual ~BSSM() = default;
};

struct SSM1 : BSSM {
    auto operator()() {
        return boost::sml::make_transition_table(
            *boost::sml::state<S1> + boost::sml::event<E1> = boost::sml::X
        );
    }
};

struct SM {
    auto operator()() {
        return boost::sml::make_transition_table(
            *boost::sml::state<SSM1> = boost::sml::X
        );
    }
};

int main() {
    using sm_type = boost::sml::sm<SM>;
    sm_type sm{};
    sm.process_event(E1{});
    return 0;
}

I get compilation errors on GCC 15.1 and Clang 18.1.0 upwards (Clang 17 seems to work though). MSVC currently doesn't complain. The errors are very similar, so I'll show the Clang one:

<source>:1491:56: error: call to constructor of 'aux::conditional_t<aux::should_not_subclass_statemachine_class<sm_policy<SSM1>>::value, aux::none_type, typename sm_policy<SSM1>::sm>' (aka 'SSM1') is ambiguous
 1491 |   constexpr sm_impl(const TPool &p, aux::false_type) : sm_t{aux::try_get<sm_t>(&p)}, transitions_{(*this)()} {
      |                                                        ^   ~~~~~~~~~~~~~~~~~~~~~~~~
<source>:1489:50: note: in instantiation of function template specialization 'boost::sml::back::sm_impl<boost::sml::back::sm_policy<SSM1>>::sm_impl<boost::sml::aux::pool<>>' requested here
 1489 |   constexpr sm_impl(aux::init, const TPool &p) : sm_impl{p, aux::should_not_subclass_statemachine_class<Tsm>{}} {}
      |                                                  ^
<source>:378:54: note: in instantiation of function template specialization 'boost::sml::back::sm_impl<boost::sml::back::sm_policy<SSM1>>::sm_impl<boost::sml::aux::pool<>>' requested here
  378 |   constexpr pool_type_impl(init i, TObject object) : value{i, object} {}
      |                                                      ^
<source>:468:45: note: in instantiation of function template specialization 'boost::sml::aux::pool_type_impl<boost::sml::back::sm_impl<boost::sml::back::sm_policy<SSM1>>>::pool_type_impl<boost::sml::aux::pool<>>' requested here
  468 |   constexpr pool(const pool<TArgs...> &p) : pool_type<Ts>(init{}, p)... {}
      |                                             ^
<source>:1845:55: note: in instantiation of function template specialization 'boost::sml::aux::pool<boost::sml::back::sm_impl<boost::sml::back::sm_policy<SM>>, boost::sml::back::sm_impl<boost::sml::back::sm_policy<SSM1>>>::pool<>' requested here
 1845 |   constexpr sm() : deps_{aux::init{}, aux::pool<>{}}, sub_sms_{aux::pool<>{}} { aux::get<sm_impl<Tsm>>(sub_sms_).start(deps_, sub_sms_); }
      |                                                       ^
<source>:2937:13: note: in instantiation of member function 'boost::sml::back::sm<boost::sml::back::sm_policy<SM>>::sm' requested here
 2937 |     sm_type sm{};
      |             ^
<source>:2919:8: note: candidate constructor (the implicit copy constructor)
 2919 | struct SSM1 : BSSM {
      |        ^
<source>:2919:8: note: candidate constructor (the implicit move constructor)
1 error generated.
Compiler returned: 1

This is tested with the current master branch of SML and 1.1.11.

The issue is with the virtual destructor of BSSM - if I make it non-virtual then the problem goes away. If I change SSM1 so that it has no bases but a virtual destructor then I get a slightly different set of compiler errors (although I think the gist is largely the same).

I haven't yet succeeded in finding a combination of copy/move constructors that lets this compile.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions