c++17state-machinestd-variantvisitors

invalid declarator before std::variant


I'm trying to implement an ad-hoc light weight state machine using std::variant. However, it seems that the variant fsm isn't declared right as it fails with the following errors:

<source>: In function 'int main()':
<source>:235:40: error: invalid declarator before 'fsm'
  235 |     std::variant<states::A, states::B> fsm{std::in_place_index<0>};
      |                                        ^~~
<source>:238:5: error: 'fsm' was not declared in this scope
  238 |     fsm = std::visit([&](auto&& state){ state.on_event(eWifi::connected); }, fsm);
      |     ^~~
ASM generation compiler returned: 1
<source>: In function 'int main()':
<source>:235:40: error: invalid declarator before 'fsm'
  235 |     std::variant<states::A, states::B> fsm{std::in_place_index<0>};
      |                                        ^~~
<source>:238:5: error: 'fsm' was not declared in this scope
  238 |     fsm = std::visit([&](auto&& state){ state.on_event(eWifi::connected); }, fsm);
      |     ^~~

I can't really get behind what is wrong. Here's the code:

#include <iostream>
#include <variant>

enum class eWifi {
    connected,
    disconnected,
};

enum class eMQTT {
    connected,
    disconnected,
};

int main()
{
    // int a;

    struct states {
        struct A {
            auto on_event(eWifi evt) {
                std::cout << "on_event A" << std::endl;
                return B{};
            }
            auto on_event(eMQTT evt) {
                std::cout << "on_event A" << std::endl;
                return B{};
            }
        };

        struct B {
            auto on_event(eWifi evt) {
                std::cout << "on_event B" << std::endl;
                return A{};
            }
            auto on_event(eMQTT evt) {
                std::cout << "on_event B" << std::endl;
                return A{};
            }
        };
    }


    std::variant<states::A, states::B> fsm{std::in_place_index<0>};

    // while(1) {
    fsm = std::visit([&](auto&& state){ state.on_event(eWifi::connected); }, fsm);
    // }
}

What is the invalid declarator before 'fsm' all about?


Solution

    1. You missed the semicolon in the declaration of struct states.
        struct states {
            struct A {
            };
    
            struct B {
            };
        };
    
    1. You forgot to return the result in your lambda function.
    fsm = std::visit([&](auto&& state) -> std::variant<states::A, states::B> {
                    return state.on_event(eWifi::connected); 
                }, fsm);
    

    See demo.