2

I am experimenting with finate state machines and std::variant<..>

std::variant will hold all possible states The states will be defined in State classes.

I'd like to have std::monostate as the first type of State variant to use it as a "do not change state" value. So the definition would be : first type is std::monostate, second type is initial state of the fsm.

As the std::variant is initialized to it's first element, I wanted to use emplace<1> in the constructor.

template <typename StateVariant>
class fsm
{
public:
    StateVariant state;
    fsm()
    {
        state.emplace<1>();
    };
};

struct Initial{};
struct Running{};

using State = std::variant<std::monostate,Initial,Running>;

fsm<State> myFSM;

But that gives compiletime error :

..\fsm_emplace.cpp: In constructor 'fsm<StateVariant>::fsm()':
..\fsm_emplace.cpp:15:20: error: expected primary-expression before ')' token
   15 |   state.emplace<1>();};

However, when i use the same construct in non template code :

State myState;

void setup()
{
    myState.emplace<1>();
}

Is there a restriction of usage for the emplace function ?

hreintke
  • 51
  • 4
  • 2
    "*As the std::variant is initialized to it's first element, I wanted to use emplace<1> in the constructor.*" Why don't you do that in the member initializer list, with [the `in_place_index_t` constructor of `variant`](https://en.cppreference.com/w/cpp/utility/variant/variant)? – Nicol Bolas Jul 09 '20 at 15:17

2 Answers2

2

As state is template name dependent, you have to add template:

state.template emplace<1>();
Jarod42
  • 203,559
  • 14
  • 181
  • 302
1

Is there a restriction of usage for the emplace function ?

I dont know the wording of the formal rules, but you need to use the template keyword here. clang gives a more descriptive error " missing 'template' keyword prior to dependent template name 'emplace'". changing state.emplace<1>(); to state.template emplace<1>(); will fix the build error.

although for what its worth i would also consider the use of in_place_index_t in the member initializer (suggested by Nicol Bolas in the comments) to be a more elegant solution.